[BACK]Return to dhcp.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / dhcp / dist / server

Annotation of src/external/mpl/dhcp/dist/server/dhcp.c, Revision 1.1.1.3

1.1       christos    1: /*     $NetBSD$        */
                      2:
                      3: /* dhcp.c
                      4:
                      5:    DHCP Protocol engine. */
                      6:
                      7: /*
1.1.1.3 ! christos    8:  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
1.1       christos    9:  * Copyright (c) 1995-2003 by Internet Software Consortium
                     10:  *
                     11:  * This Source Code Form is subject to the terms of the Mozilla Public
                     12:  * License, v. 2.0. If a copy of the MPL was not distributed with this
                     13:  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
                     14:  *
                     15:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     16:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     18:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     19:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     20:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     21:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     22:  *
                     23:  *   Internet Systems Consortium, Inc.
1.1.1.3 ! christos   24:  *   PO Box 360
        !            25:  *   Newmarket, NH 03857 USA
1.1       christos   26:  *   <info@isc.org>
                     27:  *   https://www.isc.org/
                     28:  *
                     29:  */
                     30:
                     31: #include <sys/cdefs.h>
                     32: __RCSID("$NetBSD$");
                     33:
                     34: #include "dhcpd.h"
                     35: #include <errno.h>
                     36: #include <limits.h>
                     37: #include <sys/time.h>
                     38:
                     39: static void maybe_return_agent_options(struct packet *packet,
                     40:                                       struct option_state *options);
1.1.1.2   christos   41:
1.1       christos   42: static int reuse_lease (struct packet* packet, struct lease* new_lease,
                     43:                        struct lease* lease, struct lease_state *state,
1.1.1.2   christos   44:                        int offer, int* same_client);
                     45:
                     46: static int do_ping_check(struct packet* packet, struct lease_state* state,
                     47:                          struct lease* lease, TIME original_cltt,
                     48:                         int same_client);
                     49:
1.1       christos   50: #if defined(DHCPv6) && defined(DHCP4o6)
                     51: static int locate_network6(struct packet *packet);
                     52: #endif
                     53:
                     54: int outstanding_pings;
                     55:
                     56: #if defined(DELAYED_ACK)
                     57: static void delayed_ack_enqueue(struct lease *);
                     58: static void delayed_acks_timer(void *);
                     59:
                     60:
                     61: struct leasequeue *ackqueue_head, *ackqueue_tail;
                     62: static struct leasequeue *free_ackqueue;
                     63: static struct timeval max_fsync;
                     64:
                     65: int outstanding_acks;
                     66: int max_outstanding_acks = DEFAULT_DELAYED_ACK;
                     67: int max_ack_delay_secs = DEFAULT_ACK_DELAY_SECS;
                     68: int max_ack_delay_usecs = DEFAULT_ACK_DELAY_USECS;
                     69: int min_ack_delay_usecs = DEFAULT_MIN_ACK_DELAY_USECS;
                     70: #endif
                     71:
                     72: static char dhcp_message [256];
                     73: static int site_code_min;
                     74:
                     75: static int find_min_site_code(struct universe *);
                     76: static isc_result_t lowest_site_code(const void *, unsigned, void *);
                     77:
1.1.1.2   christos   78: static const char *dhcp_type_names [] = {
1.1       christos   79:        "DHCPDISCOVER",
                     80:        "DHCPOFFER",
                     81:        "DHCPREQUEST",
                     82:        "DHCPDECLINE",
                     83:        "DHCPACK",
                     84:        "DHCPNAK",
                     85:        "DHCPRELEASE",
                     86:        "DHCPINFORM",
                     87:        "type 9",
                     88:        "DHCPLEASEQUERY",
                     89:        "DHCPLEASEUNASSIGNED",
                     90:        "DHCPLEASEUNKNOWN",
                     91:        "DHCPLEASEACTIVE"
                     92: };
                     93: const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
                     94:
                     95: #if defined (TRACING)
                     96: # define send_packet trace_packet_send
                     97: #endif
                     98:
                     99: static TIME leaseTimeCheck(TIME calculated, TIME alternate);
                    100:
                    101: void
                    102: dhcp (struct packet *packet) {
                    103:        int ms_nulltp = 0;
                    104:        struct option_cache *oc;
                    105:        struct lease *lease = NULL;
                    106:        const char *errmsg;
                    107:        struct data_string data;
                    108:
                    109:        if (!locate_network(packet) &&
                    110:            packet->packet_type != DHCPREQUEST &&
1.1.1.2   christos  111:            packet->packet_type != DHCPINFORM &&
1.1       christos  112:            packet->packet_type != DHCPLEASEQUERY) {
                    113:                const char *s;
                    114:                char typebuf[32];
                    115:                errmsg = "unknown network segment";
                    116:              bad_packet:
1.1.1.2   christos  117:
1.1       christos  118:                if (packet->packet_type > 0 &&
                    119:                    packet->packet_type <= dhcp_type_name_max) {
                    120:                        s = dhcp_type_names[packet->packet_type - 1];
                    121:                } else {
                    122:                        /* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
                    123:                        sprintf(typebuf, "type %d", packet->packet_type);
                    124:                        s = typebuf;
                    125:                }
1.1.1.2   christos  126:
1.1       christos  127: #if defined(DHCPv6) && defined(DHCP4o6)
                    128:                if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    129:                        log_info("DHCP4o6 %s from %s via %s: %s", s,
                    130:                                 (packet->raw->htype
                    131:                                  ? print_hw_addr(packet->raw->htype,
                    132:                                                  packet->raw->hlen,
                    133:                                                  packet->raw->chaddr)
                    134:                                  : "<no identifier>"),
                    135:                                 piaddr(packet->client_addr),
                    136:                                 errmsg);
                    137:                        goto out;
                    138:                }
                    139: #endif
                    140:
                    141:                log_info("%s from %s via %s: %s", s,
                    142:                         (packet->raw->htype
                    143:                          ? print_hw_addr(packet->raw->htype,
                    144:                                          packet->raw->hlen,
                    145:                                          packet->raw->chaddr)
                    146:                          : "<no identifier>"),
                    147:                         packet->raw->giaddr.s_addr
                    148:                         ? inet_ntoa(packet->raw->giaddr)
                    149:                         : packet->interface->name, errmsg);
                    150:                goto out;
                    151:        }
                    152:
                    153:        /* There is a problem with the relay agent information option,
                    154:         * which is that in order for a normal relay agent to append
                    155:         * this option, the relay agent has to have been involved in
                    156:         * getting the packet from the client to the server.  Note
                    157:         * that this is the software entity known as the relay agent,
                    158:         * _not_ the hardware entity known as a router in which the
                    159:         * relay agent may be running, so the fact that a router has
                    160:         * forwarded a packet does not mean that the relay agent in
                    161:         * the router was involved.
                    162:         *
                    163:         * So when the client broadcasts (DHCPDISCOVER, or giaddr is set),
                    164:         * we can be sure that there are either agent options in the
                    165:         * packet, or there aren't supposed to be.  When the giaddr is not
                    166:         * set, it's still possible that the client is on a directly
                    167:         * attached subnet, and agent options are being appended by an l2
                    168:         * device that has no address, and so sets no giaddr.
                    169:         *
                    170:         * But in either case it's possible that the packets we receive
                    171:         * from the client in RENEW state may not include the agent options,
                    172:         * so if they are not in the packet we must "pretend" the last values
                    173:         * we observed were provided.
                    174:         */
                    175:        if (packet->packet_type == DHCPREQUEST &&
                    176:            packet->raw->ciaddr.s_addr && !packet->raw->giaddr.s_addr &&
                    177:            (packet->options->universe_count <= agent_universe.index ||
                    178:             packet->options->universes[agent_universe.index] == NULL))
                    179:        {
                    180:                struct iaddr cip;
                    181:
                    182:                cip.len = sizeof packet -> raw -> ciaddr;
                    183:                memcpy (cip.iabuf, &packet -> raw -> ciaddr,
                    184:                        sizeof packet -> raw -> ciaddr);
                    185:                if (!find_lease_by_ip_addr (&lease, cip, MDL))
                    186:                        goto nolease;
                    187:
                    188:                /* If there are no agent options on the lease, it's not
                    189:                   interesting. */
                    190:                if (!lease -> agent_options)
                    191:                        goto nolease;
                    192:
                    193:                /* The client should not be unicasting a renewal if its lease
                    194:                   has expired, so make it go through the process of getting
                    195:                   its agent options legally. */
                    196:                if (lease -> ends < cur_time)
                    197:                        goto nolease;
                    198:
                    199:                if (lease -> uid_len) {
                    200:                        oc = lookup_option (&dhcp_universe, packet -> options,
                    201:                                            DHO_DHCP_CLIENT_IDENTIFIER);
                    202:                        if (!oc)
                    203:                                goto nolease;
                    204:
                    205:                        memset (&data, 0, sizeof data);
                    206:                        if (!evaluate_option_cache (&data,
                    207:                                                    packet, (struct lease *)0,
                    208:                                                    (struct client_state *)0,
                    209:                                                    packet -> options,
                    210:                                                    (struct option_state *)0,
                    211:                                                    &global_scope, oc, MDL))
                    212:                                goto nolease;
                    213:                        if (lease -> uid_len != data.len ||
                    214:                            memcmp (lease -> uid, data.data, data.len)) {
                    215:                                data_string_forget (&data, MDL);
                    216:                                goto nolease;
                    217:                        }
                    218:                        data_string_forget (&data, MDL);
                    219:                } else
                    220:                        if ((lease -> hardware_addr.hbuf [0] !=
                    221:                             packet -> raw -> htype) ||
                    222:                            (lease -> hardware_addr.hlen - 1 !=
                    223:                             packet -> raw -> hlen) ||
                    224:                            memcmp (&lease -> hardware_addr.hbuf [1],
                    225:                                    packet -> raw -> chaddr,
                    226:                                    packet -> raw -> hlen))
                    227:                                goto nolease;
                    228:
                    229:                /* Okay, so we found a lease that matches the client. */
                    230:                option_chain_head_reference ((struct option_chain_head **)
                    231:                                             &(packet -> options -> universes
                    232:                                               [agent_universe.index]),
                    233:                                             lease -> agent_options, MDL);
                    234:
                    235:                if (packet->options->universe_count <= agent_universe.index)
                    236:                        packet->options->universe_count =
                    237:                                                agent_universe.index + 1;
                    238:
                    239:                packet->agent_options_stashed = ISC_TRUE;
                    240:        }
                    241:       nolease:
                    242:
                    243:        /* If a client null terminates options it sends, it probably
                    244:         * expects the server to reciprocate.
                    245:         */
                    246:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                    247:                                 DHO_HOST_NAME))) {
                    248:                if (!oc -> expression)
                    249:                        ms_nulltp = oc->flags & OPTION_HAD_NULLS;
                    250:        }
                    251:
                    252:        /* Classify the client. */
                    253:        classify_client (packet);
                    254:
                    255:        switch (packet -> packet_type) {
                    256:              case DHCPDISCOVER:
                    257:                dhcpdiscover (packet, ms_nulltp);
                    258:                break;
                    259:
                    260:              case DHCPREQUEST:
                    261:                dhcprequest (packet, ms_nulltp, lease);
                    262:                break;
                    263:
                    264:              case DHCPRELEASE:
                    265:                dhcprelease (packet, ms_nulltp);
                    266:                break;
                    267:
                    268:              case DHCPDECLINE:
                    269:                dhcpdecline (packet, ms_nulltp);
                    270:                break;
                    271:
                    272:              case DHCPINFORM:
                    273:                dhcpinform (packet, ms_nulltp);
                    274:                break;
                    275:
                    276:              case DHCPLEASEQUERY:
                    277:                dhcpleasequery(packet, ms_nulltp);
                    278:                break;
                    279:
                    280:              case DHCPACK:
                    281:              case DHCPOFFER:
                    282:              case DHCPNAK:
                    283:              case DHCPLEASEUNASSIGNED:
                    284:              case DHCPLEASEUNKNOWN:
                    285:              case DHCPLEASEACTIVE:
                    286:                break;
                    287:
                    288:              default:
                    289:                errmsg = "unknown packet type";
                    290:                goto bad_packet;
                    291:        }
                    292:       out:
                    293:        if (lease)
                    294:                lease_dereference (&lease, MDL);
                    295: }
                    296:
                    297: void dhcpdiscover (packet, ms_nulltp)
                    298:        struct packet *packet;
                    299:        int ms_nulltp;
                    300: {
                    301:        struct lease *lease = (struct lease *)0;
                    302:        char msgbuf [1024]; /* XXX */
                    303:        TIME when;
                    304:        const char *s;
                    305:        int peer_has_leases = 0;
                    306: #if defined (FAILOVER_PROTOCOL)
                    307:        dhcp_failover_state_t *peer;
                    308: #endif
                    309:
                    310:        find_lease (&lease, packet, packet -> shared_network,
                    311:                    0, &peer_has_leases, (struct lease *)0, MDL);
                    312:
                    313:        if (lease && lease -> client_hostname) {
                    314:                if ((strlen (lease -> client_hostname) <= 64) &&
                    315:                    db_printable((unsigned char *)lease->client_hostname))
                    316:                        s = lease -> client_hostname;
                    317:                else
                    318:                        s = "Hostname Unsuitable for Printing";
                    319:        } else
                    320:                s = (char *)0;
                    321:
                    322:        /* %Audit% This is log output. %2004.06.17,Safe%
                    323:         * If we truncate we hope the user can get a hint from the log.
                    324:         */
                    325: #if defined(DHCPv6) && defined(DHCP4o6)
                    326:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    327:                snprintf (msgbuf, sizeof msgbuf,
                    328:                          "DHCP4o6 DHCPDISCOVER from %s %s%s%svia %s",
                    329:                          (packet -> raw -> htype
                    330:                           ? print_hw_addr (packet -> raw -> htype,
                    331:                                            packet -> raw -> hlen,
                    332:                                            packet -> raw -> chaddr)
                    333:                           : (lease
                    334:                              ? print_hex_1(lease->uid_len, lease->uid, 60)
                    335:                              : "<no identifier>")),
                    336:                          s ? "(" : "", s ? s : "", s ? ") " : "",
                    337:                          piaddr(packet->client_addr));
                    338:        } else
                    339: #endif
                    340:        snprintf (msgbuf, sizeof msgbuf, "DHCPDISCOVER from %s %s%s%svia %s",
                    341:                 (packet -> raw -> htype
                    342:                  ? print_hw_addr (packet -> raw -> htype,
                    343:                                   packet -> raw -> hlen,
                    344:                                   packet -> raw -> chaddr)
                    345:                  : (lease
                    346:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
                    347:                     : "<no identifier>")),
                    348:                  s ? "(" : "", s ? s : "", s ? ") " : "",
                    349:                  packet -> raw -> giaddr.s_addr
                    350:                  ? inet_ntoa (packet -> raw -> giaddr)
                    351:                  : packet -> interface -> name);
                    352:
                    353:        /* Sourceless packets don't make sense here. */
                    354:        if (!packet -> shared_network) {
                    355: #if defined(DHCPv6) && defined(DHCP4o6)
                    356:                if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    357:                        log_info ("DHCP4o6 packet from unknown subnet: %s",
                    358:                                  piaddr(packet->client_addr));
                    359:                } else
                    360: #endif
                    361:                log_info ("Packet from unknown subnet: %s",
                    362:                      inet_ntoa (packet -> raw -> giaddr));
                    363:                goto out;
                    364:        }
                    365:
                    366: #if defined (FAILOVER_PROTOCOL)
                    367:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
                    368:                peer = lease -> pool -> failover_peer;
                    369:
                    370:                /*
                    371:                 * If the lease is ours to (re)allocate, then allocate it.
                    372:                 *
                    373:                 * If the lease is active, it belongs to the client.  This
                    374:                 * is the right lease, if we are to offer one.  We decide
                    375:                 * whether or not to offer later on.
                    376:                 *
                    377:                 * If the lease was last active, and we've reached this
                    378:                 * point, then it was last active with the same client.  We
                    379:                 * can safely re-activate the lease with this client.
                    380:                 */
                    381:                if (lease->binding_state == FTS_ACTIVE ||
                    382:                    lease->rewind_binding_state == FTS_ACTIVE ||
                    383:                    lease_mine_to_reallocate(lease)) {
                    384:                        ; /* This space intentionally left blank. */
                    385:
                    386:                /* Otherwise, we can't let the client have this lease. */
                    387:                } else {
                    388: #if defined (DEBUG_FIND_LEASE)
                    389:                    log_debug ("discarding %s - %s",
                    390:                               piaddr (lease -> ip_addr),
                    391:                               binding_state_print (lease -> binding_state));
                    392: #endif
                    393:                    lease_dereference (&lease, MDL);
                    394:                }
                    395:        }
                    396: #endif
                    397:
                    398:        /* If we didn't find a lease, try to allocate one... */
                    399:        if (!lease) {
                    400:                if (!allocate_lease (&lease, packet,
1.1.1.2   christos  401:                                     packet -> shared_network -> pools,
1.1       christos  402:                                     &peer_has_leases)) {
                    403:                        if (peer_has_leases)
                    404:                                log_error ("%s: peer holds all free leases",
                    405:                                           msgbuf);
                    406:                        else
                    407:                                log_error ("%s: network %s: no free leases",
                    408:                                           msgbuf,
                    409:                                           packet -> shared_network -> name);
                    410:                        return;
                    411:                }
                    412:        }
                    413:
                    414: #if defined (FAILOVER_PROTOCOL)
                    415:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
                    416:                peer = lease -> pool -> failover_peer;
                    417:                if (peer -> service_state == not_responding ||
                    418:                    peer -> service_state == service_startup) {
                    419:                        log_info ("%s: not responding%s",
                    420:                                  msgbuf, peer -> nrr);
                    421:                        goto out;
                    422:                }
                    423:        } else
                    424:                peer = (dhcp_failover_state_t *)0;
                    425:
                    426:        /* Do load balancing if configured. */
                    427:        if (peer && (peer -> service_state == cooperating) &&
                    428:            !load_balance_mine (packet, peer)) {
                    429:                if (peer_has_leases) {
                    430:                        log_debug ("%s: load balance to peer %s",
                    431:                                   msgbuf, peer -> name);
                    432:                        goto out;
                    433:                } else {
                    434:                        log_debug ("%s: cancel load balance to peer %s - %s",
                    435:                                   msgbuf, peer -> name, "no free leases");
                    436:                }
                    437:        }
                    438: #endif
                    439:
                    440:        /* If it's an expired lease, get rid of any bindings. */
                    441:        if (lease -> ends < cur_time && lease -> scope)
                    442:                binding_scope_dereference (&lease -> scope, MDL);
                    443:
                    444:        /* Set the lease to really expire in 2 minutes, unless it has
                    445:           not yet expired, in which case leave its expiry time alone. */
                    446:        when = cur_time + 120;
                    447:        if (when < lease -> ends)
                    448:                when = lease -> ends;
                    449:
                    450:        ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp,
                    451:                   (struct host_decl *)0);
                    452:       out:
                    453:        if (lease)
                    454:                lease_dereference (&lease, MDL);
                    455: }
                    456:
                    457: void dhcprequest (packet, ms_nulltp, ip_lease)
                    458:        struct packet *packet;
                    459:        int ms_nulltp;
                    460:        struct lease *ip_lease;
                    461: {
                    462:        struct lease *lease;
                    463:        struct iaddr cip;
                    464:        struct iaddr sip;
                    465:        struct subnet *subnet;
                    466:        int ours = 0;
                    467:        struct option_cache *oc;
                    468:        struct data_string data;
                    469:        char msgbuf [1024]; /* XXX */
                    470:        const char *s;
                    471:        char smbuf [19];
                    472: #if defined (FAILOVER_PROTOCOL)
                    473:        dhcp_failover_state_t *peer;
                    474: #endif
                    475:        int have_requested_addr = 0;
                    476:
                    477:        oc = lookup_option (&dhcp_universe, packet -> options,
                    478:                            DHO_DHCP_REQUESTED_ADDRESS);
                    479:        memset (&data, 0, sizeof data);
                    480:        if (oc &&
                    481:            evaluate_option_cache (&data, packet, (struct lease *)0,
                    482:                                   (struct client_state *)0,
                    483:                                   packet -> options, (struct option_state *)0,
                    484:                                   &global_scope, oc, MDL)) {
                    485:                cip.len = 4;
                    486:                memcpy (cip.iabuf, data.data, 4);
                    487:                data_string_forget (&data, MDL);
                    488:                have_requested_addr = 1;
                    489:        } else {
                    490:                oc = (struct option_cache *)0;
                    491:                cip.len = 4;
                    492:                memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
                    493:        }
                    494:
                    495:        /* Find the lease that matches the address requested by the
                    496:           client. */
                    497:
                    498:        subnet = (struct subnet *)0;
                    499:        lease = (struct lease *)0;
                    500:        if (find_subnet (&subnet, cip, MDL))
                    501:                find_lease (&lease, packet,
                    502:                            subnet -> shared_network, &ours, 0, ip_lease, MDL);
                    503:
                    504:        if (lease && lease -> client_hostname) {
                    505:                if ((strlen (lease -> client_hostname) <= 64) &&
                    506:                    db_printable((unsigned char *)lease->client_hostname))
                    507:                        s = lease -> client_hostname;
                    508:                else
                    509:                        s = "Hostname Unsuitable for Printing";
                    510:        } else
                    511:                s = (char *)0;
                    512:
                    513:        oc = lookup_option (&dhcp_universe, packet -> options,
                    514:                            DHO_DHCP_SERVER_IDENTIFIER);
                    515:        memset (&data, 0, sizeof data);
                    516:        if (oc &&
                    517:            evaluate_option_cache (&data, packet, (struct lease *)0,
                    518:                                   (struct client_state *)0,
                    519:                                   packet -> options, (struct option_state *)0,
                    520:                                   &global_scope, oc, MDL)) {
                    521:                sip.len = 4;
                    522:                memcpy (sip.iabuf, data.data, 4);
                    523:                data_string_forget (&data, MDL);
                    524:                /* piaddr() should not return more than a 15 byte string.
                    525:                 * safe.
                    526:                 */
                    527:                sprintf (smbuf, " (%s)", piaddr (sip));
                    528:        } else {
                    529:                smbuf [0] = 0;
                    530:                sip.len = 0;
                    531:        }
                    532:
                    533:        /* %Audit% This is log output. %2004.06.17,Safe%
                    534:         * If we truncate we hope the user can get a hint from the log.
                    535:         */
                    536: #if defined(DHCPv6) && defined(DHCP4o6)
                    537:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    538:                snprintf (msgbuf, sizeof msgbuf,
                    539:                          "DHCP4o6 DHCPREQUEST for %s%s from %s %s%s%svia %s",
                    540:                          piaddr (cip), smbuf,
                    541:                          (packet -> raw -> htype
                    542:                           ? print_hw_addr (packet -> raw -> htype,
                    543:                                            packet -> raw -> hlen,
                    544:                                            packet -> raw -> chaddr)
                    545:                           : (lease
                    546:                              ? print_hex_1(lease->uid_len, lease->uid, 60)
                    547:                              : "<no identifier>")),
                    548:                          s ? "(" : "", s ? s : "", s ? ") " : "",
                    549:                          piaddr(packet->client_addr));
                    550:        } else
                    551: #endif
                    552:        snprintf (msgbuf, sizeof msgbuf,
                    553:                 "DHCPREQUEST for %s%s from %s %s%s%svia %s",
                    554:                 piaddr (cip), smbuf,
                    555:                 (packet -> raw -> htype
                    556:                  ? print_hw_addr (packet -> raw -> htype,
                    557:                                   packet -> raw -> hlen,
                    558:                                   packet -> raw -> chaddr)
                    559:                  : (lease
                    560:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
                    561:                     : "<no identifier>")),
                    562:                 s ? "(" : "", s ? s : "", s ? ") " : "",
                    563:                  packet -> raw -> giaddr.s_addr
                    564:                  ? inet_ntoa (packet -> raw -> giaddr)
                    565:                  : packet -> interface -> name);
                    566:
                    567: #if defined (FAILOVER_PROTOCOL)
                    568:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
                    569:                peer = lease -> pool -> failover_peer;
                    570:                if (peer -> service_state == not_responding ||
                    571:                    peer -> service_state == service_startup) {
                    572:                        log_info ("%s: not responding%s",
                    573:                                  msgbuf, peer -> nrr);
                    574:                        goto out;
                    575:                }
                    576:
                    577:                /* "load balance to peer" - is not done at all for request.
                    578:                 *
                    579:                 * If it's RENEWING, we are the only server to hear it, so
                    580:                 * we have to serve it.   If it's REBINDING, it's out of
                    581:                 * communication with the other server, so there's no point
                    582:                 * in waiting to serve it.    However, if the lease we're
                    583:                 * offering is not a free lease, then we may be the only
                    584:                 * server that can offer it, so we can't load balance if
                    585:                 * the lease isn't in the free or backup state.  If it is
                    586:                 * in the free or backup state, then that state is what
                    587:                 * mandates one server or the other should perform the
                    588:                 * allocation, not the LBA...we know the peer cannot
                    589:                 * allocate a request for an address in our free state.
                    590:                 *
                    591:                 * So our only compass is lease_mine_to_reallocate().  This
                    592:                 * effects both load balancing, and a sanity-check that we
                    593:                 * are not going to try to allocate a lease that isn't ours.
                    594:                 */
                    595:                if ((lease -> binding_state == FTS_FREE ||
                    596:                     lease -> binding_state == FTS_BACKUP) &&
                    597:                    !lease_mine_to_reallocate (lease)) {
                    598:                        log_debug ("%s: lease owned by peer", msgbuf);
                    599:                        goto out;
                    600:                }
                    601:
                    602:                /*
                    603:                 * If the lease is in a transitional state, we can't
                    604:                 * renew it unless we can rewind it to a non-transitional
                    605:                 * state (active, free, or backup).  lease_mine_to_reallocate()
                    606:                 * checks for free/backup, so we only need to check for active.
                    607:                 */
                    608:                if ((lease->binding_state == FTS_RELEASED ||
                    609:                     lease->binding_state == FTS_EXPIRED) &&
                    610:                    lease->rewind_binding_state != FTS_ACTIVE &&
                    611:                    !lease_mine_to_reallocate(lease)) {
                    612:                        log_debug("%s: lease in transition state %s", msgbuf,
                    613:                                  (lease->binding_state == FTS_RELEASED)
                    614:                                   ? "released" : "expired");
                    615:                        goto out;
                    616:                }
                    617:
                    618:                /* It's actually very unlikely that we'll ever get here,
                    619:                   but if we do, tell the client to stop using the lease,
                    620:                   because the administrator reset it. */
                    621:                if (lease -> binding_state == FTS_RESET &&
                    622:                    !lease_mine_to_reallocate (lease)) {
                    623:                        log_debug ("%s: lease reset by administrator", msgbuf);
                    624:                        nak_lease (packet, &cip, lease->subnet->group);
                    625:                        goto out;
                    626:                }
                    627:
                    628:                /* If server-id-check is enabled, verify that the client's
                    629:                 * server source address (sip from incoming packet) is ours.
                    630:                 * To avoid problems with confused clients we do some sanity
                    631:                 * checks to verify sip's length and that it isn't all zeros.
                    632:                 * We then get the server id we would likely use for this
                    633:                 * packet and compare them.  If they don't match it we assume
                    634:                 * we didn't send the offer and so we don't process the
                    635:                 * request. */
                    636:                if ((server_id_check == 1) && (sip.len == 4) &&
                    637:                    (memcmp(sip.iabuf, "\0\0\0\0", sip.len) != 0)) {
                    638:                        struct in_addr from;
                    639:                        struct option_state *eval_options = NULL;
                    640:
                    641:                        eval_network_statements(&eval_options, packet, NULL);
                    642:                        get_server_source_address(&from, eval_options,
                    643:                                                  NULL, packet);
                    644:                        option_state_dereference (&eval_options, MDL);
                    645:                        if (memcmp(sip.iabuf, &from, sip.len) != 0) {
                    646:                                log_debug("%s: not our server id", msgbuf);
                    647:                                goto out;
                    648:                        }
                    649:                }
                    650:
                    651:                /* At this point it's possible that we will get a broadcast
                    652:                   DHCPREQUEST for a lease that we didn't offer, because
                    653:                   both we and the peer are in a position to offer it.
                    654:                   In that case, we probably shouldn't answer.   In order
                    655:                   to not answer, we would have to compare the server
                    656:                   identifier sent by the client with the list of possible
                    657:                   server identifiers we can send, and if the client's
                    658:                   identifier isn't on the list, drop the DHCPREQUEST.
                    659:                   We aren't currently doing that for two reasons - first,
                    660:                   it's not clear that all clients do the right thing
                    661:                   with respect to sending the client identifier, which
                    662:                   could mean that we might simply not respond to a client
                    663:                   that is depending on us to respond.   Secondly, we allow
                    664:                   the user to specify the server identifier to send, and
                    665:                   we don't enforce that the server identifier should be
                    666:                   one of our IP addresses.   This is probably not a big
                    667:                   deal, but it's theoretically an issue.
                    668:
                    669:                   The reason we care about this is that if both servers
                    670:                   send a DHCPACK to the DHCPREQUEST, they are then going
                    671:                   to send dueling BNDUPD messages, which could cause
                    672:                   trouble.   I think it causes no harm, but it seems
                    673:                   wrong. */
                    674:        } else
                    675:                peer = (dhcp_failover_state_t *)0;
                    676: #endif
                    677:
                    678:        /* If a client on a given network REQUESTs a lease on an
                    679:           address on a different network, NAK it.  If the Requested
                    680:           Address option was used, the protocol says that it must
                    681:           have been broadcast, so we can trust the source network
                    682:           information.
                    683:
                    684:           If ciaddr was specified and Requested Address was not, then
                    685:           we really only know for sure what network a packet came from
                    686:           if it came through a BOOTP gateway - if it came through an
                    687:           IP router, we'll just have to assume that it's cool.
                    688:
                    689:           If we don't think we know where the packet came from, it
                    690:           came through a gateway from an unknown network, so it's not
                    691:           from a RENEWING client.  If we recognize the network it
                    692:           *thinks* it's on, we can NAK it even though we don't
                    693:           recognize the network it's *actually* on; otherwise we just
                    694:           have to ignore it.
                    695:
                    696:           We don't currently try to take advantage of access to the
                    697:           raw packet, because it's not available on all platforms.
                    698:           So a packet that was unicast to us through a router from a
                    699:           RENEWING client is going to look exactly like a packet that
                    700:           was broadcast to us from an INIT-REBOOT client.
                    701:
                    702:           Since we can't tell the difference between these two kinds
                    703:           of packets, if the packet appears to have come in off the
                    704:           local wire, we have to treat it as if it's a RENEWING
                    705:           client.  This means that we can't NAK a RENEWING client on
                    706:           the local wire that has a bogus address.  The good news is
                    707:           that we won't ACK it either, so it should revert to INIT
                    708:           state and send us a DHCPDISCOVER, which we *can* work with.
                    709:
                    710:           Because we can't detect that a RENEWING client is on the
                    711:           wrong wire, it's going to sit there trying to renew until
                    712:           it gets to the REBIND state, when we *can* NAK it because
                    713:           the packet will get to us through a BOOTP gateway.  We
                    714:           shouldn't actually see DHCPREQUEST packets from RENEWING
                    715:           clients on the wrong wire anyway, since their idea of their
                    716:           local router will be wrong.  In any case, the protocol
                    717:           doesn't really allow us to NAK a DHCPREQUEST from a
                    718:           RENEWING client, so we can punt on this issue. */
                    719:
                    720:        if (!packet -> shared_network ||
                    721:            (packet -> raw -> ciaddr.s_addr &&
                    722:             packet -> raw -> giaddr.s_addr) ||
                    723:            (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
1.1.1.2   christos  724:
1.1       christos  725:                /* If we don't know where it came from but we do know
                    726:                   where it claims to have come from, it didn't come
                    727:                   from there. */
                    728:                if (!packet -> shared_network) {
                    729:                        if (subnet && subnet -> group -> authoritative) {
                    730:                                log_info ("%s: wrong network.", msgbuf);
                    731:                                nak_lease (packet, &cip, NULL);
                    732:                                goto out;
                    733:                        }
                    734:                        /* Otherwise, ignore it. */
                    735:                        log_info ("%s: ignored (%s).", msgbuf,
                    736:                                  (subnet
                    737:                                   ? "not authoritative" : "unknown subnet"));
                    738:                        goto out;
                    739:                }
                    740:
                    741:                /* If we do know where it came from and it asked for an
                    742:                   address that is not on that shared network, nak it. */
                    743:                if (subnet)
                    744:                        subnet_dereference (&subnet, MDL);
                    745:                if (!find_grouped_subnet (&subnet, packet -> shared_network,
                    746:                                          cip, MDL)) {
                    747:                        if (packet -> shared_network -> group -> authoritative)
                    748:                        {
                    749:                                log_info ("%s: wrong network.", msgbuf);
                    750:                                nak_lease (packet, &cip, NULL);
                    751:                                goto out;
                    752:                        }
                    753:                        log_info ("%s: ignored (not authoritative).", msgbuf);
                    754:                        return;
                    755:                }
                    756:        }
                    757:
                    758:        /* If the address the client asked for is ours, but it wasn't
                    759:           available for the client, NAK it. */
                    760:        if (!lease && ours) {
                    761:                log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
                    762:                nak_lease (packet, &cip, (subnet ? subnet->group : NULL));
                    763:                goto out;
                    764:        }
                    765:
                    766:        /* Otherwise, send the lease to the client if we found one. */
                    767:        if (lease) {
                    768:                ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp,
                    769:                           (struct host_decl *)0);
                    770:        } else
                    771:                log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
                    772:
                    773:       out:
                    774:        if (subnet)
                    775:                subnet_dereference (&subnet, MDL);
                    776:        if (lease)
                    777:                lease_dereference (&lease, MDL);
                    778:        return;
                    779: }
                    780:
                    781: void dhcprelease (packet, ms_nulltp)
                    782:        struct packet *packet;
                    783:        int ms_nulltp;
                    784: {
                    785:        struct lease *lease = (struct lease *)0, *next = (struct lease *)0;
                    786:        struct iaddr cip;
                    787:        struct option_cache *oc;
                    788:        struct data_string data;
                    789:        const char *s;
                    790:        char msgbuf [1024], cstr[16]; /* XXX */
                    791:
                    792:
                    793:        /* DHCPRELEASE must not specify address in requested-address
                    794:           option, but old protocol specs weren't explicit about this,
                    795:           so let it go. */
                    796:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                    797:                                 DHO_DHCP_REQUESTED_ADDRESS))) {
                    798:                log_info ("DHCPRELEASE from %s specified requested-address.",
                    799:                      print_hw_addr (packet -> raw -> htype,
                    800:                                     packet -> raw -> hlen,
                    801:                                     packet -> raw -> chaddr));
                    802:        }
                    803:
                    804:        oc = lookup_option (&dhcp_universe, packet -> options,
                    805:                            DHO_DHCP_CLIENT_IDENTIFIER);
                    806:        memset (&data, 0, sizeof data);
                    807:        if (oc &&
                    808:            evaluate_option_cache (&data, packet, (struct lease *)0,
                    809:                                   (struct client_state *)0,
                    810:                                   packet -> options, (struct option_state *)0,
                    811:                                   &global_scope, oc, MDL)) {
                    812:                find_lease_by_uid (&lease, data.data, data.len, MDL);
                    813:                data_string_forget (&data, MDL);
                    814:
                    815:                /* See if we can find a lease that matches the IP address
                    816:                   the client is claiming. */
                    817:                while (lease) {
                    818:                        if (lease -> n_uid)
                    819:                                lease_reference (&next, lease -> n_uid, MDL);
                    820:                        if (!memcmp (&packet -> raw -> ciaddr,
                    821:                                     lease -> ip_addr.iabuf, 4)) {
                    822:                                break;
                    823:                        }
                    824:                        lease_dereference (&lease, MDL);
                    825:                        if (next) {
                    826:                                lease_reference (&lease, next, MDL);
                    827:                                lease_dereference (&next, MDL);
                    828:                        }
                    829:                }
                    830:                if (next)
                    831:                        lease_dereference (&next, MDL);
                    832:        }
                    833:
                    834:        /* The client is supposed to pass a valid client-identifier,
                    835:           but the spec on this has changed historically, so try the
                    836:           IP address in ciaddr if the client-identifier fails. */
                    837:        if (!lease) {
                    838:                cip.len = 4;
                    839:                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
                    840:                find_lease_by_ip_addr (&lease, cip, MDL);
                    841:        }
                    842:
                    843:
                    844:        /* If the hardware address doesn't match, don't do the release. */
                    845:        if (lease &&
                    846:            (lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
                    847:             lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
                    848:             memcmp (&lease -> hardware_addr.hbuf [1],
                    849:                     packet -> raw -> chaddr, packet -> raw -> hlen)))
                    850:                lease_dereference (&lease, MDL);
                    851:
                    852:        if (lease && lease -> client_hostname) {
                    853:                if ((strlen (lease -> client_hostname) <= 64) &&
                    854:                    db_printable((unsigned char *)lease->client_hostname))
                    855:                        s = lease -> client_hostname;
                    856:                else
                    857:                        s = "Hostname Unsuitable for Printing";
                    858:        } else
                    859:                s = (char *)0;
                    860:
                    861:        /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe%
                    862:         * We copy this out to stack because we actually want to log two
                    863:         * inet_ntoa()'s in this message.
                    864:         */
                    865:        strncpy(cstr, inet_ntoa (packet -> raw -> ciaddr), 15);
                    866:        cstr[15] = '\0';
                    867:
                    868:        /* %Audit% This is log output. %2004.06.17,Safe%
                    869:         * If we truncate we hope the user can get a hint from the log.
                    870:         */
                    871: #if defined(DHCPv6) && defined(DHCP4o6)
                    872:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    873:                snprintf (msgbuf, sizeof msgbuf,
                    874:                          "DHCP4o6 DHCPRELEASE of %s from %s %s%s%svia "
                    875:                          "%s (%sfound)",
                    876:                          cstr,
                    877:                          (packet -> raw -> htype
                    878:                           ? print_hw_addr (packet -> raw -> htype,
                    879:                                            packet -> raw -> hlen,
                    880:                                            packet -> raw -> chaddr)
                    881:                           : (lease
                    882:                              ? print_hex_1(lease->uid_len, lease->uid, 60)
                    883:                              : "<no identifier>")),
                    884:                          s ? "(" : "", s ? s : "", s ? ") " : "",
                    885:                          piaddr(packet->client_addr),
                    886:                          lease ? "" : "not ");
                    887:        } else
                    888: #endif
                    889:        snprintf (msgbuf, sizeof msgbuf,
                    890:                 "DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
                    891:                 cstr,
                    892:                 (packet -> raw -> htype
                    893:                  ? print_hw_addr (packet -> raw -> htype,
                    894:                                   packet -> raw -> hlen,
                    895:                                   packet -> raw -> chaddr)
                    896:                  : (lease
                    897:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
                    898:                     : "<no identifier>")),
                    899:                 s ? "(" : "", s ? s : "", s ? ") " : "",
                    900:                 packet -> raw -> giaddr.s_addr
                    901:                 ? inet_ntoa (packet -> raw -> giaddr)
                    902:                 : packet -> interface -> name,
                    903:                 lease ? "" : "not ");
                    904:
                    905: #if defined (FAILOVER_PROTOCOL)
                    906:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
                    907:                dhcp_failover_state_t *peer = lease -> pool -> failover_peer;
                    908:                if (peer -> service_state == not_responding ||
                    909:                    peer -> service_state == service_startup) {
                    910:                        log_info ("%s: ignored%s",
                    911:                                  peer -> name, peer -> nrr);
                    912:                        goto out;
                    913:                }
                    914:
                    915:                /* DHCPRELEASE messages are unicast, so if the client
                    916:                   sent the DHCPRELEASE to us, it's not going to send it
                    917:                   to the peer.   Not sure why this would happen, and
                    918:                   if it does happen I think we still have to change the
                    919:                   lease state, so that's what we're doing.
                    920:                   XXX See what it says in the draft about this. */
                    921:        }
                    922: #endif
                    923:
                    924:        /* If we found a lease, release it. */
                    925:        if (lease && lease -> ends > cur_time) {
                    926:                release_lease (lease, packet);
1.1.1.2   christos  927:        }
1.1       christos  928:        log_info ("%s", msgbuf);
                    929: #if defined(FAILOVER_PROTOCOL)
                    930:       out:
                    931: #endif
                    932:        if (lease)
                    933:                lease_dereference (&lease, MDL);
                    934: }
                    935:
                    936: void dhcpdecline (packet, ms_nulltp)
                    937:        struct packet *packet;
                    938:        int ms_nulltp;
                    939: {
                    940:        struct lease *lease = (struct lease *)0;
                    941:        struct option_state *options = (struct option_state *)0;
                    942:        int ignorep = 0;
                    943:        int i;
                    944:        const char *status;
                    945:        const char *s;
                    946:        char msgbuf [1024]; /* XXX */
                    947:        struct iaddr cip;
                    948:        struct option_cache *oc;
                    949:        struct data_string data;
                    950:
                    951:        /* DHCPDECLINE must specify address. */
                    952:        if (!(oc = lookup_option (&dhcp_universe, packet -> options,
                    953:                                  DHO_DHCP_REQUESTED_ADDRESS)))
                    954:                return;
                    955:        memset (&data, 0, sizeof data);
                    956:        if (!evaluate_option_cache (&data, packet, (struct lease *)0,
                    957:                                    (struct client_state *)0,
                    958:                                    packet -> options,
                    959:                                    (struct option_state *)0,
                    960:                                    &global_scope, oc, MDL))
                    961:                return;
                    962:
                    963:        cip.len = 4;
                    964:        memcpy (cip.iabuf, data.data, 4);
                    965:        data_string_forget (&data, MDL);
                    966:        find_lease_by_ip_addr (&lease, cip, MDL);
                    967:
                    968:        if (lease && lease -> client_hostname) {
                    969:                if ((strlen (lease -> client_hostname) <= 64) &&
                    970:                    db_printable((unsigned char *)lease->client_hostname))
                    971:                        s = lease -> client_hostname;
                    972:                else
                    973:                        s = "Hostname Unsuitable for Printing";
                    974:        } else
                    975:                s = (char *)0;
                    976:
                    977:        /* %Audit% This is log output. %2004.06.17,Safe%
                    978:         * If we truncate we hope the user can get a hint from the log.
                    979:         */
                    980: #if defined(DHCPv6) && defined(DHCP4o6)
                    981:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                    982:                snprintf (msgbuf, sizeof msgbuf,
                    983:                          "DHCP4o6 DHCPDECLINE of %s from %s %s%s%svia %s",
                    984:                          piaddr (cip),
                    985:                          (packet -> raw -> htype
                    986:                           ? print_hw_addr (packet -> raw -> htype,
                    987:                                            packet -> raw -> hlen,
                    988:                                            packet -> raw -> chaddr)
                    989:                           : (lease
                    990:                              ? print_hex_1(lease->uid_len, lease->uid, 60)
                    991:                              : "<no identifier>")),
                    992:                          s ? "(" : "", s ? s : "", s ? ") " : "",
                    993:                          piaddr(packet->client_addr));
                    994:        } else
                    995: #endif
                    996:        snprintf (msgbuf, sizeof msgbuf,
                    997:                 "DHCPDECLINE of %s from %s %s%s%svia %s",
                    998:                 piaddr (cip),
                    999:                 (packet -> raw -> htype
                   1000:                  ? print_hw_addr (packet -> raw -> htype,
                   1001:                                   packet -> raw -> hlen,
                   1002:                                   packet -> raw -> chaddr)
                   1003:                  : (lease
                   1004:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
                   1005:                     : "<no identifier>")),
                   1006:                 s ? "(" : "", s ? s : "", s ? ") " : "",
                   1007:                 packet -> raw -> giaddr.s_addr
                   1008:                 ? inet_ntoa (packet -> raw -> giaddr)
                   1009:                 : packet -> interface -> name);
                   1010:
                   1011:        option_state_allocate (&options, MDL);
                   1012:
                   1013:        /* Execute statements in scope starting with the subnet scope. */
                   1014:        if (lease)
                   1015:                execute_statements_in_scope(NULL, packet, NULL, NULL,
                   1016:                                            packet->options, options,
                   1017:                                            &global_scope,
                   1018:                                            lease->subnet->group,
                   1019:                                            NULL, NULL);
                   1020:
                   1021:        /* Execute statements in the class scopes. */
                   1022:        for (i = packet -> class_count; i > 0; i--) {
                   1023:                execute_statements_in_scope
                   1024:                        (NULL, packet, NULL, NULL, packet->options, options,
                   1025:                         &global_scope, packet->classes[i - 1]->group,
                   1026:                         lease ? lease->subnet->group : NULL, NULL);
                   1027:        }
                   1028:
                   1029:        /* Drop the request if dhcpdeclines are being ignored. */
                   1030:        oc = lookup_option (&server_universe, options, SV_DECLINES);
                   1031:        if (!oc ||
                   1032:            evaluate_boolean_option_cache (&ignorep, packet, lease,
                   1033:                                           (struct client_state *)0,
                   1034:                                           packet -> options, options,
                   1035:                                           &lease -> scope, oc, MDL)) {
                   1036:            /* If we found a lease, mark it as unusable and complain. */
                   1037:            if (lease) {
                   1038: #if defined (FAILOVER_PROTOCOL)
                   1039:                if (lease -> pool && lease -> pool -> failover_peer) {
                   1040:                    dhcp_failover_state_t *peer =
                   1041:                            lease -> pool -> failover_peer;
                   1042:                    if (peer -> service_state == not_responding ||
                   1043:                        peer -> service_state == service_startup) {
                   1044:                        if (!ignorep)
                   1045:                            log_info ("%s: ignored%s",
                   1046:                                      peer -> name, peer -> nrr);
                   1047:                        goto out;
                   1048:                    }
                   1049:
                   1050:                    /* DHCPDECLINE messages are broadcast, so we can safely
                   1051:                       ignore the DHCPDECLINE if the peer has the lease.
                   1052:                       XXX Of course, at this point that information has been
                   1053:                       lost. */
                   1054:                }
                   1055: #endif
                   1056:
                   1057:                abandon_lease (lease, "declined.");
                   1058:                status = "abandoned";
                   1059:            } else {
                   1060:                status = "not found";
                   1061:            }
                   1062:        } else
                   1063:            status = "ignored";
                   1064:
                   1065:        if (!ignorep)
                   1066:                log_info ("%s: %s", msgbuf, status);
                   1067:
                   1068: #if defined(FAILOVER_PROTOCOL)
                   1069:       out:
                   1070: #endif
                   1071:        if (options)
                   1072:                option_state_dereference (&options, MDL);
                   1073:        if (lease)
                   1074:                lease_dereference (&lease, MDL);
                   1075: }
                   1076:
                   1077: #if defined(RELAY_PORT)
                   1078: u_int16_t dhcp_check_relayport(packet)
                   1079:        struct packet *packet;
                   1080: {
                   1081:        if (lookup_option(&agent_universe,
                   1082:                          packet->options,
                   1083:                          RAI_RELAY_PORT) != NULL) {
                   1084:                return (packet->client_port);
                   1085:        }
                   1086:
                   1087:        return (0);
                   1088: }
                   1089: #endif
                   1090:
                   1091: void dhcpinform (packet, ms_nulltp)
                   1092:        struct packet *packet;
                   1093:        int ms_nulltp;
                   1094: {
                   1095:        char msgbuf[1024], *addr_type;
                   1096:        struct data_string d1, prl, fixed_addr;
                   1097:        struct option_cache *oc;
                   1098:        struct option_state *options = NULL;
                   1099:        struct dhcp_packet raw;
                   1100:        struct packet outgoing;
                   1101:        unsigned char dhcpack = DHCPACK;
                   1102:        struct subnet *subnet = NULL;
                   1103:        struct iaddr cip, gip, sip;
                   1104:        unsigned i;
                   1105:        int nulltp;
                   1106:        struct sockaddr_in to;
                   1107:        struct in_addr from;
                   1108:        isc_boolean_t zeroed_ciaddr;
                   1109:        struct interface_info *interface;
                   1110:        int result, h_m_client_ip = 0;
                   1111:        struct host_decl  *host = NULL, *hp = NULL, *h;
                   1112: #if defined(RELAY_PORT)
                   1113:        u_int16_t relay_port = 0;
                   1114: #endif
                   1115: #if defined (DEBUG_INFORM_HOST)
                   1116:        int h_w_fixed_addr = 0;
                   1117: #endif
                   1118:
                   1119:        /* The client should set ciaddr to its IP address, but apparently
                   1120:           it's common for clients not to do this, so we'll use their IP
                   1121:           source address if they didn't set ciaddr. */
                   1122:        if (!packet->raw->ciaddr.s_addr) {
                   1123:                zeroed_ciaddr = ISC_TRUE;
                   1124:                /* With DHCPv4-over-DHCPv6 it can be an IPv6 address
                   1125:                   so we check its length. */
                   1126:                if (packet->client_addr.len == 4) {
                   1127:                        cip.len = 4;
                   1128:                        memcpy(cip.iabuf, &packet->client_addr.iabuf, 4);
                   1129:                        addr_type = "source";
                   1130:                } else {
                   1131:                        cip.len = 0;
                   1132:                        memset(cip.iabuf, 0, 4);
                   1133:                        addr_type = "v4o6";
                   1134:                }
                   1135:        } else {
                   1136:                zeroed_ciaddr = ISC_FALSE;
                   1137:                cip.len = 4;
                   1138:                memcpy(cip.iabuf, &packet->raw->ciaddr, 4);
                   1139:                addr_type = "client";
                   1140:        }
                   1141:        sip.len = 4;
                   1142:        memcpy(sip.iabuf, cip.iabuf, 4);
                   1143:
                   1144:        if (packet->raw->giaddr.s_addr) {
                   1145:                gip.len = 4;
                   1146:                memcpy(gip.iabuf, &packet->raw->giaddr, 4);
                   1147:                if (zeroed_ciaddr == ISC_TRUE) {
                   1148:                        addr_type = "relay";
                   1149:                        memcpy(sip.iabuf, gip.iabuf, 4);
                   1150:                }
                   1151:        } else
                   1152:                gip.len = 0;
                   1153:
                   1154:        /* %Audit% This is log output. %2004.06.17,Safe%
                   1155:         * If we truncate we hope the user can get a hint from the log.
                   1156:         */
                   1157: #if defined(DHCPv6) && defined(DHCP4o6)
                   1158:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                   1159:                snprintf(msgbuf, sizeof(msgbuf),
                   1160:                         "DHCP4o6 DHCPINFORM from %s via %s",
                   1161:                         piaddr(cip),
                   1162:                         piaddr(packet->client_addr));
                   1163:        } else
                   1164: #endif
                   1165:        snprintf(msgbuf, sizeof(msgbuf), "DHCPINFORM from %s via %s",
                   1166:                 piaddr(cip),
                   1167:                 packet->raw->giaddr.s_addr ?
                   1168:                 inet_ntoa(packet->raw->giaddr) :
                   1169:                 packet->interface->name);
                   1170:
                   1171:        /* If the IP source address is zero, don't respond. */
                   1172:        if (!memcmp(cip.iabuf, "\0\0\0", 4)) {
                   1173:                log_info("%s: ignored (null source address).", msgbuf);
                   1174:                return;
                   1175:        }
                   1176:
                   1177: #if defined(RELAY_PORT)
                   1178:        relay_port = dhcp_check_relayport(packet);
                   1179: #endif
                   1180:
1.1.1.2   christos 1181:        /* Find the subnet that the client is on.
1.1       christos 1182:         * CC: Do the link selection / subnet selection
                   1183:         */
                   1184:
                   1185:        option_state_allocate(&options, MDL);
                   1186:
                   1187:        if ((oc = lookup_option(&agent_universe, packet->options,
                   1188:                                RAI_LINK_SELECT)) == NULL)
                   1189:                oc = lookup_option(&dhcp_universe, packet->options,
                   1190:                                   DHO_SUBNET_SELECTION);
                   1191:
                   1192:        memset(&d1, 0, sizeof d1);
                   1193:        if (oc && evaluate_option_cache(&d1, packet, NULL, NULL,
                   1194:                                        packet->options, NULL,
                   1195:                                        &global_scope, oc, MDL)) {
                   1196:                struct option_cache *noc = NULL;
                   1197:
                   1198:                if (d1.len != 4) {
                   1199:                        log_info("%s: ignored (invalid subnet selection option).", msgbuf);
                   1200:                        option_state_dereference(&options, MDL);
1.1.1.2   christos 1201:                        data_string_forget(&d1, MDL);
1.1       christos 1202:                        return;
                   1203:                }
                   1204:
                   1205:                memcpy(sip.iabuf, d1.data, 4);
                   1206:                data_string_forget(&d1, MDL);
                   1207:
                   1208:                /* Make a copy of the data. */
                   1209:                if (option_cache_allocate(&noc, MDL)) {
                   1210:                        if (oc->data.len)
                   1211:                                data_string_copy(&noc->data, &oc->data, MDL);
                   1212:                        if (oc->expression)
                   1213:                                expression_reference(&noc->expression,
                   1214:                                                     oc->expression, MDL);
                   1215:                        if (oc->option)
                   1216:                                option_reference(&(noc->option), oc->option,
                   1217:                                                 MDL);
                   1218:                }
                   1219:                save_option(&dhcp_universe, options, noc);
                   1220:                option_cache_dereference(&noc, MDL);
                   1221:
                   1222:                if ((zeroed_ciaddr == ISC_TRUE) && (gip.len != 0))
                   1223:                        addr_type = "relay link select";
                   1224:                else
                   1225:                        addr_type = "selected";
                   1226:        }
                   1227:
                   1228:        find_subnet(&subnet, sip, MDL);
                   1229:
                   1230:        if (subnet == NULL) {
                   1231:                log_info("%s: unknown subnet for %s address %s",
                   1232:                         msgbuf, addr_type, piaddr(sip));
                   1233:                option_state_dereference(&options, MDL);
                   1234:                return;
                   1235:        }
                   1236:
                   1237:        /* We don't respond to DHCPINFORM packets if we're not authoritative.
                   1238:           It would be nice if a per-host value could override this, but
                   1239:           there's overhead involved in checking this, so let's see how people
                   1240:           react first. */
                   1241:        if (!subnet->group->authoritative) {
                   1242:                static int eso = 0;
                   1243:                log_info("%s: not authoritative for subnet %s",
                   1244:                          msgbuf, piaddr (subnet -> net));
                   1245:                if (!eso) {
                   1246:                        log_info("If this DHCP server is authoritative for%s",
                   1247:                                  " that subnet,");
                   1248:                        log_info("please write an `authoritative;' directi%s",
                   1249:                                  "ve either in the");
                   1250:                        log_info("subnet declaration or in some scope that%s",
                   1251:                                  " encloses the");
                   1252:                        log_info("subnet declaration - for example, write %s",
                   1253:                                  "it at the top");
                   1254:                        log_info("of the dhcpd.conf file.");
                   1255:                }
                   1256:                if (eso++ == 100)
                   1257:                        eso = 0;
                   1258:                subnet_dereference(&subnet, MDL);
                   1259:                option_state_dereference(&options, MDL);
                   1260:                return;
                   1261:        }
1.1.1.2   christos 1262:
1.1       christos 1263:        memset(&outgoing, 0, sizeof outgoing);
                   1264:        memset(&raw, 0, sizeof raw);
                   1265:        outgoing.raw = &raw;
                   1266:
                   1267:        maybe_return_agent_options(packet, options);
                   1268:
                   1269:        /* Execute statements network statements starting at the subnet level */
                   1270:        execute_statements_in_scope(NULL, packet, NULL, NULL,
                   1271:                                    packet->options, options,
                   1272:                                    &global_scope, subnet->group,
                   1273:                                    NULL, NULL);
                   1274:
                   1275:        /* If we have ciaddr, find its lease so we can find its pool. */
                   1276:        if (zeroed_ciaddr == ISC_FALSE) {
                   1277:                struct lease* cip_lease = NULL;
                   1278:
                   1279:                find_lease_by_ip_addr (&cip_lease, cip, MDL);
1.1.1.2   christos 1280:
                   1281:                /* Overlay with pool options if ciaddr mapped to a lease. */
1.1       christos 1282:                if (cip_lease) {
                   1283:                        if (cip_lease->pool && cip_lease->pool->group) {
                   1284:                                execute_statements_in_scope(
                   1285:                                        NULL, packet, NULL, NULL,
                   1286:                                        packet->options, options,
                   1287:                                        &global_scope,
                   1288:                                        cip_lease->pool->group,
                   1289:                                        cip_lease->pool->shared_network->group,
                   1290:                                        NULL);
                   1291:                        }
                   1292:
                   1293:                        lease_dereference (&cip_lease, MDL);
                   1294:                }
                   1295:        }
1.1.1.2   christos 1296:
1.1       christos 1297:        /* Execute statements in the class scopes. */
                   1298:        for (i = packet->class_count; i > 0; i--) {
                   1299:                execute_statements_in_scope(NULL, packet, NULL, NULL,
                   1300:                                            packet->options, options,
                   1301:                                            &global_scope,
                   1302:                                            packet->classes[i - 1]->group,
                   1303:                                            subnet->group,
                   1304:                                            NULL);
                   1305:        }
                   1306:
                   1307:        /*
1.1.1.2   christos 1308:         * Process host declarations during DHCPINFORM,
1.1       christos 1309:         * Try to find a matching host declaration by cli ID or HW addr.
                   1310:         *
                   1311:         * Look through the host decls for one that matches the
                   1312:         * client identifer or the hardware address.  The preference
                   1313:         * order is:
                   1314:         * client id with matching ip address
                   1315:         * hardware address with matching ip address
                   1316:         * client id without a ip fixed address
                   1317:         * hardware address without a fixed ip address
                   1318:         * If found, set host to use its option definitions.
                   1319:          */
                   1320:        oc = lookup_option(&dhcp_universe, packet->options,
                   1321:                           DHO_DHCP_CLIENT_IDENTIFIER);
                   1322:        memset(&d1, 0, sizeof(d1));
                   1323:        if (oc &&
                   1324:            evaluate_option_cache(&d1, packet, NULL, NULL,
                   1325:                                  packet->options, NULL,
                   1326:                                  &global_scope, oc, MDL)) {
                   1327:                find_hosts_by_uid(&hp, d1.data, d1.len, MDL);
                   1328:                data_string_forget(&d1, MDL);
                   1329:
                   1330: #if defined (DEBUG_INFORM_HOST)
                   1331:                if (hp)
                   1332:                        log_debug ("dhcpinform: found host by ID "
                   1333:                                   "-- checking fixed-address match");
                   1334: #endif
                   1335:                /* check if we have one with fixed-address
                   1336:                 * matching the client ip first */
                   1337:                for (h = hp; !h_m_client_ip && h; h = h->n_ipaddr) {
                   1338:                        if (!h->fixed_addr)
                   1339:                                continue;
                   1340:
                   1341:                        memset(&fixed_addr, 0, sizeof(fixed_addr));
                   1342:                        if (!evaluate_option_cache (&fixed_addr, NULL,
                   1343:                                                    NULL, NULL, NULL, NULL,
                   1344:                                                    &global_scope,
                   1345:                                                    h->fixed_addr, MDL))
                   1346:                                continue;
                   1347:
                   1348: #if defined (DEBUG_INFORM_HOST)
                   1349:                        h_w_fixed_addr++;
                   1350: #endif
                   1351:                        for (i = 0;
                   1352:                             (i + cip.len) <= fixed_addr.len;
                   1353:                             i += cip.len) {
                   1354:                                if (memcmp(fixed_addr.data + i,
                   1355:                                           cip.iabuf, cip.len) == 0) {
                   1356: #if defined (DEBUG_INFORM_HOST)
                   1357:                                        log_debug ("dhcpinform: found "
                   1358:                                                   "host with matching "
                   1359:                                                   "fixed-address by ID");
                   1360: #endif
                   1361:                                        host_reference(&host, h, MDL);
                   1362:                                        h_m_client_ip = 1;
                   1363:                                        break;
                   1364:                                }
                   1365:                        }
                   1366:                        data_string_forget(&fixed_addr, MDL);
                   1367:                }
                   1368:
                   1369:                /* fallback to a host without fixed-address */
                   1370:                for (h = hp; !host && h; h = h->n_ipaddr) {
                   1371:                        if (h->fixed_addr)
                   1372:                                continue;
                   1373:
                   1374: #if defined (DEBUG_INFORM_HOST)
                   1375:                        log_debug ("dhcpinform: found host "
                   1376:                                   "without fixed-address by ID");
                   1377: #endif
                   1378:                        host_reference(&host, h, MDL);
                   1379:                        break;
                   1380:                }
                   1381:                if (hp)
                   1382:                        host_dereference (&hp, MDL);
                   1383:        }
                   1384:        if (!host || !h_m_client_ip) {
                   1385:                find_hosts_by_haddr(&hp, packet->raw->htype,
                   1386:                                    packet->raw->chaddr,
                   1387:                                    packet->raw->hlen, MDL);
                   1388:
                   1389: #if defined (DEBUG_INFORM_HOST)
                   1390:                if (hp)
                   1391:                        log_debug ("dhcpinform: found host by HW "
                   1392:                                   "-- checking fixed-address match");
                   1393: #endif
                   1394:
                   1395:                /* check if we have one with fixed-address
                   1396:                 * matching the client ip first */
                   1397:                for (h = hp; !h_m_client_ip && h; h = h->n_ipaddr) {
                   1398:                        if (!h->fixed_addr)
                   1399:                                continue;
                   1400:
                   1401:                        memset (&fixed_addr, 0, sizeof(fixed_addr));
                   1402:                        if (!evaluate_option_cache (&fixed_addr, NULL,
                   1403:                                                    NULL, NULL, NULL, NULL,
                   1404:                                                    &global_scope,
                   1405:                                                    h->fixed_addr, MDL))
                   1406:                                continue;
                   1407:
                   1408: #if defined (DEBUG_INFORM_HOST)
                   1409:                        h_w_fixed_addr++;
                   1410: #endif
                   1411:                        for (i = 0;
                   1412:                             (i + cip.len) <= fixed_addr.len;
                   1413:                             i += cip.len) {
                   1414:                                if (memcmp(fixed_addr.data + i,
                   1415:                                           cip.iabuf, cip.len) == 0) {
                   1416: #if defined (DEBUG_INFORM_HOST)
                   1417:                                        log_debug ("dhcpinform: found "
                   1418:                                                   "host with matching "
                   1419:                                                   "fixed-address by HW");
                   1420: #endif
                   1421:                                        /*
                   1422:                                         * Hmm.. we've found one
                   1423:                                         * without IP by ID and now
                   1424:                                         * (better) one with IP by HW.
                   1425:                                         */
                   1426:                                        if(host)
                   1427:                                                host_dereference(&host, MDL);
                   1428:                                        host_reference(&host, h, MDL);
                   1429:                                        h_m_client_ip = 1;
                   1430:                                        break;
                   1431:                                }
                   1432:                        }
                   1433:                        data_string_forget(&fixed_addr, MDL);
                   1434:                }
                   1435:                /* fallback to a host without fixed-address */
                   1436:                for (h = hp; !host && h; h = h->n_ipaddr) {
                   1437:                        if (h->fixed_addr)
                   1438:                                continue;
                   1439:
                   1440: #if defined (DEBUG_INFORM_HOST)
                   1441:                        log_debug ("dhcpinform: found host without "
                   1442:                                   "fixed-address by HW");
                   1443: #endif
                   1444:                        host_reference (&host, h, MDL);
                   1445:                        break;
                   1446:                }
                   1447:
                   1448:                if (hp)
                   1449:                        host_dereference (&hp, MDL);
                   1450:        }
1.1.1.2   christos 1451:
1.1       christos 1452: #if defined (DEBUG_INFORM_HOST)
                   1453:        /* Hmm..: what when there is a host with a fixed-address,
                   1454:         * that matches by hw or id, but the fixed-addresses
                   1455:         * didn't match client ip?
                   1456:         */
                   1457:        if (h_w_fixed_addr && !h_m_client_ip) {
                   1458:                log_info ("dhcpinform: matching host with "
                   1459:                          "fixed-address different than "
                   1460:                          "client IP detected?!");
                   1461:        }
                   1462: #endif
                   1463:
                   1464:        /* If we have a host_decl structure, run the options
                   1465:         * associated with its group. Whether the host decl
                   1466:         * struct is old or not. */
                   1467:        if (host) {
                   1468: #if defined (DEBUG_INFORM_HOST)
                   1469:                log_info ("dhcpinform: applying host (group) options");
                   1470: #endif
                   1471:                execute_statements_in_scope(NULL, packet, NULL, NULL,
                   1472:                                            packet->options, options,
                   1473:                                            &global_scope, host->group,
                   1474:                                            subnet->group,
                   1475:                                            NULL);
                   1476:                host_dereference (&host, MDL);
                   1477:        }
                   1478:
                   1479:        /* CC: end of host entry processing.... */
1.1.1.2   christos 1480:
1.1       christos 1481:        /* Figure out the filename. */
                   1482:        memset (&d1, 0, sizeof d1);
                   1483:        oc = lookup_option (&server_universe, options, SV_FILENAME);
                   1484:        if (oc &&
                   1485:            evaluate_option_cache (&d1, packet, (struct lease *)0,
                   1486:                                   (struct client_state *)0,
                   1487:                                   packet -> options, (struct option_state *)0,
                   1488:                                   &global_scope, oc, MDL)) {
                   1489:                i = d1.len;
                   1490:                if (i >= sizeof(raw.file)) {
                   1491:                        log_info("file name longer than packet field "
1.1.1.2   christos 1492:                                 "truncated - field: %lu name: %d %.*s",
1.1       christos 1493:                                 (unsigned long)sizeof(raw.file), i,
                   1494:                                 (int)i, d1.data);
                   1495:                        i = sizeof(raw.file);
                   1496:                } else
                   1497:                        raw.file[i] = 0;
                   1498:                memcpy (raw.file, d1.data, i);
                   1499:                data_string_forget (&d1, MDL);
                   1500:        }
                   1501:
                   1502:        /* Choose a server name as above. */
                   1503:        oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
                   1504:        if (oc &&
                   1505:            evaluate_option_cache (&d1, packet, (struct lease *)0,
                   1506:                                   (struct client_state *)0,
                   1507:                                   packet -> options, (struct option_state *)0,
                   1508:                                   &global_scope, oc, MDL)) {
                   1509:                i = d1.len;
                   1510:                if (i >= sizeof(raw.sname)) {
                   1511:                        log_info("server name longer than packet field "
1.1.1.2   christos 1512:                                 "truncated - field: %lu name: %d %.*s",
1.1       christos 1513:                                 (unsigned long)sizeof(raw.sname), i,
                   1514:                                 (int)i, d1.data);
                   1515:                        i = sizeof(raw.sname);
                   1516:                } else
                   1517:                        raw.sname[i] = 0;
                   1518:                memcpy (raw.sname, d1.data, i);
                   1519:                data_string_forget (&d1, MDL);
                   1520:        }
                   1521:
                   1522:        /* Set a flag if this client is a lame Microsoft client that NUL
                   1523:           terminates string options and expects us to do likewise. */
                   1524:        nulltp = 0;
                   1525:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                   1526:                                 DHO_HOST_NAME))) {
                   1527:                if (!oc->expression)
                   1528:                        nulltp = oc->flags & OPTION_HAD_NULLS;
                   1529:        }
                   1530:
                   1531:        /* Put in DHCP-specific options. */
                   1532:        i = DHO_DHCP_MESSAGE_TYPE;
                   1533:        oc = (struct option_cache *)0;
                   1534:        if (option_cache_allocate (&oc, MDL)) {
                   1535:                if (make_const_data (&oc -> expression,
                   1536:                                     &dhcpack, 1, 0, 0, MDL)) {
                   1537:                        option_code_hash_lookup(&oc->option,
                   1538:                                                dhcp_universe.code_hash,
                   1539:                                                &i, 0, MDL);
                   1540:                        save_option (&dhcp_universe, options, oc);
                   1541:                }
                   1542:                option_cache_dereference (&oc, MDL);
                   1543:        }
                   1544:
                   1545:        get_server_source_address(&from, options, options, packet);
                   1546:
                   1547:        /* Use the subnet mask from the subnet declaration if no other
                   1548:           mask has been provided. */
                   1549:        i = DHO_SUBNET_MASK;
                   1550:        if (subnet && !lookup_option (&dhcp_universe, options, i)) {
                   1551:                oc = (struct option_cache *)0;
                   1552:                if (option_cache_allocate (&oc, MDL)) {
                   1553:                        if (make_const_data (&oc -> expression,
                   1554:                                             subnet -> netmask.iabuf,
                   1555:                                             subnet -> netmask.len,
                   1556:                                             0, 0, MDL)) {
                   1557:                                option_code_hash_lookup(&oc->option,
                   1558:                                                        dhcp_universe.code_hash,
                   1559:                                                        &i, 0, MDL);
                   1560:                                save_option (&dhcp_universe, options, oc);
                   1561:                        }
                   1562:                        option_cache_dereference (&oc, MDL);
                   1563:                }
                   1564:        }
                   1565:
                   1566:        /* If a site option space has been specified, use that for
                   1567:           site option codes. */
                   1568:        i = SV_SITE_OPTION_SPACE;
                   1569:        if ((oc = lookup_option (&server_universe, options, i)) &&
                   1570:            evaluate_option_cache (&d1, packet, (struct lease *)0,
                   1571:                                   (struct client_state *)0,
                   1572:                                   packet -> options, options,
                   1573:                                   &global_scope, oc, MDL)) {
                   1574:                struct universe *u = (struct universe *)0;
                   1575:
                   1576:                if (!universe_hash_lookup (&u, universe_hash,
                   1577:                                           (const char *)d1.data, d1.len,
                   1578:                                           MDL)) {
                   1579:                        log_error ("unknown option space %s.", d1.data);
                   1580:                        option_state_dereference (&options, MDL);
                   1581:                        if (subnet)
                   1582:                                subnet_dereference (&subnet, MDL);
1.1.1.2   christos 1583:                        data_string_forget (&d1, MDL);
1.1       christos 1584:                        return;
                   1585:                }
                   1586:
                   1587:                options -> site_universe = u -> index;
                   1588:                options->site_code_min = find_min_site_code(u);
                   1589:                data_string_forget (&d1, MDL);
                   1590:        } else {
                   1591:                options -> site_universe = dhcp_universe.index;
                   1592:                options -> site_code_min = 0; /* Trust me, it works. */
                   1593:        }
                   1594:
                   1595:        memset (&prl, 0, sizeof prl);
                   1596:
                   1597:        /* Use the parameter list from the scope if there is one. */
                   1598:        oc = lookup_option (&dhcp_universe, options,
                   1599:                            DHO_DHCP_PARAMETER_REQUEST_LIST);
                   1600:
                   1601:        /* Otherwise, if the client has provided a list of options
                   1602:           that it wishes returned, use it to prioritize.  Otherwise,
                   1603:           prioritize based on the default priority list. */
                   1604:
                   1605:        if (!oc)
                   1606:                oc = lookup_option (&dhcp_universe, packet -> options,
                   1607:                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
                   1608:
                   1609:        if (oc)
                   1610:                evaluate_option_cache (&prl, packet, (struct lease *)0,
                   1611:                                       (struct client_state *)0,
                   1612:                                       packet -> options, options,
                   1613:                                       &global_scope, oc, MDL);
                   1614:
                   1615: #ifdef DEBUG_PACKET
                   1616:        dump_packet (packet);
                   1617:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
                   1618: #endif
                   1619:
                   1620:        log_info ("%s", msgbuf);
                   1621:
                   1622:        /* Figure out the address of the boot file server. */
                   1623:        if ((oc =
                   1624:             lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
                   1625:                if (evaluate_option_cache (&d1, packet, (struct lease *)0,
                   1626:                                           (struct client_state *)0,
                   1627:                                           packet -> options, options,
                   1628:                                           &global_scope, oc, MDL)) {
                   1629:                        /* If there was more than one answer,
                   1630:                           take the first. */
                   1631:                        if (d1.len >= 4 && d1.data)
                   1632:                                memcpy (&raw.siaddr, d1.data, 4);
                   1633:                        data_string_forget (&d1, MDL);
                   1634:                }
                   1635:        }
                   1636:
                   1637:        /*
                   1638:         * Remove any time options, per section 3.4 RFC 2131
                   1639:         */
                   1640:        delete_option(&dhcp_universe, options, DHO_DHCP_LEASE_TIME);
                   1641:        delete_option(&dhcp_universe, options, DHO_DHCP_RENEWAL_TIME);
                   1642:        delete_option(&dhcp_universe, options, DHO_DHCP_REBINDING_TIME);
                   1643:
                   1644:        /* Set up the option buffer... */
                   1645:        outgoing.packet_length =
                   1646:                cons_options (packet, outgoing.raw, (struct lease *)0,
                   1647:                              (struct client_state *)0,
                   1648:                              0, packet -> options, options, &global_scope,
                   1649:                              0, nulltp, 0,
                   1650:                              prl.len ? &prl : (struct data_string *)0,
                   1651:                              (char *)0);
                   1652:        option_state_dereference (&options, MDL);
                   1653:        data_string_forget (&prl, MDL);
                   1654:
                   1655:        /* Make sure that the packet is at least as big as a BOOTP packet. */
                   1656:        if (outgoing.packet_length < BOOTP_MIN_LEN)
                   1657:                outgoing.packet_length = BOOTP_MIN_LEN;
                   1658:
                   1659:        raw.giaddr = packet -> raw -> giaddr;
                   1660:        raw.ciaddr = packet -> raw -> ciaddr;
                   1661:        memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
                   1662:        raw.hlen = packet -> raw -> hlen;
                   1663:        raw.htype = packet -> raw -> htype;
                   1664:
                   1665:        raw.xid = packet -> raw -> xid;
                   1666:        raw.secs = packet -> raw -> secs;
                   1667:        raw.flags = packet -> raw -> flags;
                   1668:        raw.hops = packet -> raw -> hops;
                   1669:        raw.op = BOOTREPLY;
                   1670:
                   1671: #ifdef DEBUG_PACKET
                   1672:        dump_packet (&outgoing);
                   1673:        dump_raw ((unsigned char *)&raw, outgoing.packet_length);
                   1674: #endif
                   1675:
                   1676: #if defined(DHCPv6) && defined(DHCP4o6)
                   1677:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                   1678:                /* Report what we're sending. */
                   1679:                snprintf(msgbuf, sizeof msgbuf,
                   1680:                         "DHCP4o6 DHCPACK to %s (%s) via", piaddr(cip),
                   1681:                         (packet->raw->htype && packet->raw->hlen) ?
                   1682:                         print_hw_addr(packet->raw->htype, packet->raw->hlen,
                   1683:                                       packet->raw->chaddr) :
                   1684:                         "<no client hardware address>");
                   1685:                log_info("%s %s", msgbuf, piaddr(packet->client_addr));
                   1686:
                   1687:                /* fill dhcp4o6_response */
                   1688:                packet->dhcp4o6_response->len = outgoing.packet_length;
                   1689:                packet->dhcp4o6_response->buffer = NULL;
                   1690:                if (!buffer_allocate(&packet->dhcp4o6_response->buffer,
                   1691:                                     outgoing.packet_length, MDL)) {
                   1692:                        log_fatal("No memory to store DHCP4o6 reply.");
                   1693:                }
                   1694:                packet->dhcp4o6_response->data =
                   1695:                        packet->dhcp4o6_response->buffer->data;
                   1696:                memcpy(packet->dhcp4o6_response->buffer->data,
                   1697:                       outgoing.raw, outgoing.packet_length);
                   1698:
                   1699:                /* done */
                   1700:                if (subnet)
                   1701:                        subnet_dereference (&subnet, MDL);
                   1702:                return;
                   1703:        }
                   1704: #endif
                   1705:
                   1706:        /* Set up the common stuff... */
                   1707:        to.sin_family = AF_INET;
                   1708: #ifdef HAVE_SA_LEN
                   1709:        to.sin_len = sizeof to;
                   1710: #endif
                   1711:        memset (to.sin_zero, 0, sizeof to.sin_zero);
                   1712:
                   1713:        /* RFC2131 states the server SHOULD unicast to ciaddr.
                   1714:         * There are two wrinkles - relays, and when ciaddr is zero.
                   1715:         * There's actually no mention of relays at all in rfc2131 in
                   1716:         * regard to DHCPINFORM, except to say we might get packets from
                   1717:         * clients via them.  Note: relays unicast to clients to the
                   1718:         * "yiaddr" address, which servers are forbidden to set when
                   1719:         * answering an inform.
                   1720:         *
                   1721:         * The solution: If ciaddr is zero, and giaddr is set, go via the
                   1722:         * relay with the broadcast flag set to help the relay (with no
                   1723:         * yiaddr and very likely no chaddr, it will have no idea where to
                   1724:         * send the packet).
                   1725:         *
                   1726:         * If the ciaddr is zero and giaddr is not set, go via the source
                   1727:         * IP address (but you are permitted to barf on their shoes).
                   1728:         *
                   1729:         * If ciaddr is not zero, send the packet there always.
                   1730:         */
                   1731:        if (!raw.ciaddr.s_addr && gip.len) {
                   1732:                memcpy(&to.sin_addr, gip.iabuf, 4);
                   1733: #if defined(RELAY_PORT)
                   1734:                to.sin_port = relay_port ? relay_port : local_port;
                   1735: #else
                   1736:                to.sin_port = local_port;
                   1737: #endif
                   1738:                raw.flags |= htons(BOOTP_BROADCAST);
                   1739:        } else {
                   1740:                gip.len = 0;
                   1741:                memcpy(&to.sin_addr, cip.iabuf, 4);
                   1742:                to.sin_port = remote_port;
                   1743:        }
                   1744:
                   1745:        /* Report what we're sending. */
                   1746:        snprintf(msgbuf, sizeof msgbuf, "DHCPACK to %s (%s) via", piaddr(cip),
                   1747:                 (packet->raw->htype && packet->raw->hlen) ?
                   1748:                        print_hw_addr(packet->raw->htype, packet->raw->hlen,
                   1749:                                      packet->raw->chaddr) :
                   1750:                        "<no client hardware address>");
                   1751:        log_info("%s %s", msgbuf, gip.len ? piaddr(gip) :
                   1752:                                            packet->interface->name);
                   1753:
                   1754:        errno = 0;
                   1755:        interface = (fallback_interface ? fallback_interface
                   1756:                     : packet -> interface);
                   1757:        result = send_packet(interface, &outgoing, &raw,
                   1758:                             outgoing.packet_length, from, &to, NULL);
                   1759:        if (result < 0) {
                   1760:                log_error ("%s:%d: Failed to send %d byte long packet over %s "
                   1761:                           "interface.", MDL, outgoing.packet_length,
                   1762:                           interface->name);
                   1763:        }
                   1764:
                   1765:
                   1766:        if (subnet)
                   1767:                subnet_dereference (&subnet, MDL);
                   1768: }
                   1769:
                   1770: /*!
                   1771:  * \brief Constructs and sends a DHCP Nak
                   1772:  *
                   1773:  * In order to populate options such as dhcp-server-id and
                   1774:  * dhcp-client-identifier, the function creates a temporary option cache
                   1775:  * and evaluates options based on the packet's shared-network or the
                   1776:  * network_group in its absence, as well as the packet->clasess (if any).
                   1777:  *
                   1778:  * \param packet inbound packet received from the client
                   1779:  * \param cip address requested by the client
                   1780:  * \param network_group optional scope for use in setting up options
                   1781:  */
                   1782: void nak_lease (packet, cip, network_group)
                   1783:        struct packet *packet;
                   1784:        struct iaddr *cip;
                   1785:        struct group *network_group; /* scope to use for options */
                   1786: {
                   1787:        struct sockaddr_in to;
                   1788:        struct in_addr from;
                   1789:        int result;
                   1790:        struct dhcp_packet raw;
                   1791:        unsigned char nak = DHCPNAK;
                   1792:        struct packet outgoing;
                   1793:        unsigned i;
                   1794: #if defined(RELAY_PORT)
                   1795:        u_int16_t relay_port = 0;
                   1796: #endif
                   1797:        struct option_state *options = (struct option_state *)0;
                   1798:        struct option_cache *oc = (struct option_cache *)0;
                   1799:        struct option_state *eval_options = NULL;
                   1800:
                   1801:        option_state_allocate (&options, MDL);
                   1802:        memset (&outgoing, 0, sizeof outgoing);
                   1803:        memset (&raw, 0, sizeof raw);
                   1804:        outgoing.raw = &raw;
                   1805:
                   1806:        /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
                   1807:        if (!option_cache_allocate (&oc, MDL)) {
                   1808:                log_error ("No memory for DHCPNAK message type.");
                   1809:                option_state_dereference (&options, MDL);
                   1810:                return;
                   1811:        }
                   1812:        if (!make_const_data (&oc -> expression, &nak, sizeof nak,
                   1813:                              0, 0, MDL)) {
                   1814:                log_error ("No memory for expr_const expression.");
                   1815:                option_cache_dereference (&oc, MDL);
                   1816:                option_state_dereference (&options, MDL);
                   1817:                return;
                   1818:        }
                   1819:        i = DHO_DHCP_MESSAGE_TYPE;
                   1820:        option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
                   1821:                                &i, 0, MDL);
                   1822:        save_option (&dhcp_universe, options, oc);
                   1823:        option_cache_dereference (&oc, MDL);
1.1.1.2   christos 1824:
1.1       christos 1825: #if defined(RELAY_PORT)
                   1826:        relay_port = dhcp_check_relayport(packet);
                   1827: #endif
                   1828:
                   1829:        /* Set DHCP_MESSAGE to whatever the message is */
                   1830:        if (!option_cache_allocate (&oc, MDL)) {
                   1831:                log_error ("No memory for DHCPNAK message type.");
                   1832:                option_state_dereference (&options, MDL);
                   1833:                return;
                   1834:        }
                   1835:        if (!make_const_data (&oc -> expression,
                   1836:                              (unsigned char *)dhcp_message,
                   1837:                              strlen (dhcp_message), 1, 0, MDL)) {
                   1838:                log_error ("No memory for expr_const expression.");
                   1839:                option_cache_dereference (&oc, MDL);
                   1840:                option_state_dereference (&options, MDL);
                   1841:                return;
                   1842:        }
                   1843:        i = DHO_DHCP_MESSAGE;
                   1844:        option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
                   1845:                                &i, 0, MDL);
                   1846:        save_option (&dhcp_universe, options, oc);
                   1847:        option_cache_dereference (&oc, MDL);
                   1848:
                   1849:        /* Setup the options at the global and subnet scopes.  These
                   1850:         * may be used to locate sever id option if enabled as well
                   1851:         * for echo-client-id further on. (This allocates eval_options). */
                   1852:        eval_network_statements(&eval_options, packet, network_group);
                   1853:
                   1854: #if defined(SERVER_ID_FOR_NAK)
                   1855:        /* Pass in the evaluated options so they can be searched for
                   1856:          * server-id, otherwise source address comes from the interface
                   1857:         * address. */
                   1858:        get_server_source_address(&from, eval_options, options, packet);
                   1859: #else
                   1860:        /* Get server source address from the interface address */
                   1861:        get_server_source_address(&from, NULL, options, packet);
                   1862: #endif /* if defined(SERVER_ID_FOR_NAK) */
                   1863:
                   1864:        /* If there were agent options in the incoming packet, return
                   1865:         * them.  We do not check giaddr to detect the presence of a
                   1866:         * relay, as this excludes "l2" relay agents which have no
                   1867:         * giaddr to set.
                   1868:         */
                   1869:        if (packet->options->universe_count > agent_universe.index &&
                   1870:            packet->options->universes [agent_universe.index]) {
                   1871:                option_chain_head_reference
                   1872:                    ((struct option_chain_head **)
                   1873:                     &(options -> universes [agent_universe.index]),
                   1874:                     (struct option_chain_head *)
                   1875:                     packet -> options -> universes [agent_universe.index],
                   1876:                     MDL);
                   1877:        }
                   1878:
                   1879:         /* echo-client-id can specified at the class level so add class-scoped
                   1880:         * options into eval_options. */
                   1881:         for (i = packet->class_count; i > 0; i--) {
                   1882:                 execute_statements_in_scope(NULL, packet, NULL, NULL,
                   1883:                                            packet->options, eval_options,
                   1884:                                            &global_scope,
                   1885:                                            packet->classes[i - 1]->group,
                   1886:                                            NULL, NULL);
                   1887:         }
                   1888:
                   1889:        /* Echo client id if we received and it's enabled */
                   1890:        echo_client_id(packet, NULL, eval_options, options);
                   1891:        option_state_dereference (&eval_options, MDL);
                   1892:
                   1893:        /* Do not use the client's requested parameter list. */
                   1894:        delete_option (&dhcp_universe, packet -> options,
                   1895:                       DHO_DHCP_PARAMETER_REQUEST_LIST);
                   1896:
                   1897:        /* Set up the option buffer... */
                   1898:        outgoing.packet_length =
                   1899:                cons_options (packet, outgoing.raw, (struct lease *)0,
                   1900:                              (struct client_state *)0,
                   1901:                              0, packet -> options, options, &global_scope,
                   1902:                              0, 0, 0, (struct data_string *)0, (char *)0);
                   1903:        option_state_dereference (&options, MDL);
                   1904:
                   1905: /*     memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
                   1906:        raw.giaddr = packet -> raw -> giaddr;
                   1907:        memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
                   1908:        raw.hlen = packet -> raw -> hlen;
                   1909:        raw.htype = packet -> raw -> htype;
                   1910:
                   1911:        raw.xid = packet -> raw -> xid;
                   1912:        raw.secs = packet -> raw -> secs;
                   1913:        raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
                   1914:        raw.hops = packet -> raw -> hops;
                   1915:        raw.op = BOOTREPLY;
                   1916:
                   1917:        /* Make sure that the packet is at least as big as a BOOTP packet. */
                   1918:        if (outgoing.packet_length < BOOTP_MIN_LEN)
                   1919:                outgoing.packet_length = BOOTP_MIN_LEN;
                   1920:
                   1921:        /* Report what we're sending... */
                   1922: #if defined(DHCPv6) && defined(DHCP4o6)
                   1923:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                   1924:                log_info ("DHCP4o6 DHCPNAK on %s to %s via %s",
                   1925:                          piaddr (*cip),
                   1926:                          print_hw_addr (packet -> raw -> htype,
                   1927:                                         packet -> raw -> hlen,
                   1928:                                         packet -> raw -> chaddr),
                   1929:                          piaddr(packet->client_addr));
                   1930:        } else
                   1931: #endif
                   1932:        log_info ("DHCPNAK on %s to %s via %s",
                   1933:              piaddr (*cip),
                   1934:              print_hw_addr (packet -> raw -> htype,
                   1935:                             packet -> raw -> hlen,
                   1936:                             packet -> raw -> chaddr),
                   1937:              packet -> raw -> giaddr.s_addr
                   1938:              ? inet_ntoa (packet -> raw -> giaddr)
                   1939:              : packet -> interface -> name);
                   1940:
                   1941: #ifdef DEBUG_PACKET
                   1942:        dump_packet (packet);
                   1943:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
                   1944:        dump_packet (&outgoing);
                   1945:        dump_raw ((unsigned char *)&raw, outgoing.packet_length);
                   1946: #endif
                   1947:
                   1948: #if defined(DHCPv6) && defined(DHCP4o6)
                   1949:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                   1950:                /* fill dhcp4o6_response */
                   1951:                packet->dhcp4o6_response->len = outgoing.packet_length;
                   1952:                packet->dhcp4o6_response->buffer = NULL;
                   1953:                if (!buffer_allocate(&packet->dhcp4o6_response->buffer,
                   1954:                                     outgoing.packet_length, MDL)) {
                   1955:                        log_fatal("No memory to store DHCP4o6 reply.");
                   1956:                }
                   1957:                packet->dhcp4o6_response->data =
                   1958:                        packet->dhcp4o6_response->buffer->data;
                   1959:                memcpy(packet->dhcp4o6_response->buffer->data,
                   1960:                       outgoing.raw, outgoing.packet_length);
                   1961:                return;
                   1962:        }
                   1963: #endif
                   1964:
                   1965:        /* Set up the common stuff... */
                   1966:        to.sin_family = AF_INET;
                   1967: #ifdef HAVE_SA_LEN
                   1968:        to.sin_len = sizeof to;
                   1969: #endif
                   1970:        memset (to.sin_zero, 0, sizeof to.sin_zero);
                   1971:
                   1972:        /* If this was gatewayed, send it back to the gateway.
                   1973:           Otherwise, broadcast it on the local network. */
                   1974:        if (raw.giaddr.s_addr) {
                   1975:                to.sin_addr = raw.giaddr;
                   1976:                if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
                   1977: #if defined(RELAY_PORT)
                   1978:                        to.sin_port = relay_port ? relay_port : local_port;
                   1979: #else
                   1980:                        to.sin_port = local_port;
                   1981: #endif
                   1982:                else
                   1983:                        to.sin_port = remote_port; /* for testing. */
                   1984:
                   1985:                if (fallback_interface) {
                   1986:                        result = send_packet(fallback_interface, packet, &raw,
                   1987:                                             outgoing.packet_length, from, &to,
                   1988:                                             NULL);
                   1989:                        if (result < 0) {
                   1990:                                log_error ("%s:%d: Failed to send %d byte long "
                   1991:                                           "packet over %s interface.", MDL,
                   1992:                                           outgoing.packet_length,
                   1993:                                           fallback_interface->name);
                   1994:                        }
                   1995:
                   1996:                        return;
                   1997:                }
                   1998:        } else {
                   1999:                to.sin_addr = limited_broadcast;
                   2000:                to.sin_port = remote_port;
                   2001:        }
                   2002:
                   2003:        errno = 0;
                   2004:        result = send_packet(packet->interface, packet, &raw,
                   2005:                             outgoing.packet_length, from, &to, NULL);
                   2006:         if (result < 0) {
                   2007:                 log_error ("%s:%d: Failed to send %d byte long packet over %s "
                   2008:                            "interface.", MDL, outgoing.packet_length,
                   2009:                            packet->interface->name);
                   2010:         }
                   2011:
                   2012: }
                   2013:
                   2014: /*!
                   2015:  * \brief Adds a dhcp-client-id option to a set of options
                   2016:  * Given a set of input options, it searches for echo-client-id.  If it is
                   2017:  * defined and enabled, the given packet is searched for dhcp-client-id.  If
                   2018:  * the option is found it is replicated into the given set of output options.
                   2019:  * This allows us to provide compliance with RFC 6842. It is called when we ack
                   2020:  * or nak a lease.  In the latter case we may or may not have created the
                   2021:  * requisite scope to lookup echo-client-id.
                   2022:  *
                   2023:  * Note the flag packet.sv_echo_client_id is set to reflect the configuration
                   2024:  * option.  This bypases inaccessiblity of server_universe in cons_options()
                   2025:  * which must amend the PRL (when not empty) if echoing is enabled.
                   2026:  *
                   2027:  * \param packet inbound packet received from the client
                   2028:  * \param lease lease associated with this client (if one)
                   2029:  * \param in_options options in which to search for echo-client-id
                   2030:  * \param out_options options to which to save the client-id
                   2031:  */
                   2032: void echo_client_id(packet, lease, in_options, out_options)
                   2033:        struct packet *packet;
                   2034:        struct lease *lease;
                   2035:        struct option_state *in_options;
                   2036:        struct option_state *out_options;
                   2037: {
                   2038:        struct option_cache *oc;
                   2039:        int ignorep;
                   2040:
                   2041:        /* Check if echo-client-id is enabled */
                   2042:        oc = lookup_option(&server_universe, in_options, SV_ECHO_CLIENT_ID);
                   2043:        if (oc && evaluate_boolean_option_cache(&ignorep, packet, lease,
                   2044:                                                 NULL, packet->options,
                   2045:                                                in_options,
                   2046:                                                 (lease ? &lease->scope : NULL),
                   2047:                                                oc, MDL)) {
                   2048:                struct data_string client_id;
                   2049:                unsigned int opcode = DHO_DHCP_CLIENT_IDENTIFIER;
                   2050:
                   2051:                /* Save knowledge that echo is enabled to the packet */
                   2052:                packet->sv_echo_client_id = ISC_TRUE;
                   2053:
                   2054:                /* Now see if inbound packet contains client-id */
                   2055:                oc = lookup_option(&dhcp_universe, packet->options, opcode);
                   2056:                memset(&client_id, 0, sizeof client_id);
                   2057:                if (oc && evaluate_option_cache(&client_id,
                   2058:                                                packet, NULL, NULL,
                   2059:                                                packet->options, NULL,
                   2060:                                                (lease ? &lease->scope : NULL),
                   2061:                                                oc, MDL)) {
                   2062:                        /* Packet contained client-id, add it to out_options. */
                   2063:                        oc = NULL;
                   2064:                        if (option_cache_allocate(&oc, MDL)) {
                   2065:                                if (make_const_data(&oc->expression,
                   2066:                                                    client_id.data,
                   2067:                                                    client_id.len,
                   2068:                                                     1, 0, MDL)) {
                   2069:                                        option_code_hash_lookup(&oc->option,
                   2070:                                                                dhcp_universe.
                   2071:                                                                 code_hash,
                   2072:                                                                &opcode,
                   2073:                                                                 0, MDL);
                   2074:                                        save_option(&dhcp_universe,
                   2075:                                                    out_options, oc);
                   2076:                                }
                   2077:                                option_cache_dereference(&oc, MDL);
                   2078:                        }
                   2079:                }
                   2080:        }
                   2081: }
                   2082:
                   2083: void check_pool_threshold (packet, lease, state)
                   2084:      struct packet *packet;
                   2085:      struct lease *lease;
                   2086:      struct lease_state *state;
                   2087:
                   2088: {
                   2089:
                   2090:        struct pool *pool = lease->pool;
                   2091:        int used, count, high_threshold, poolhigh = 0, poollow = 0;
                   2092:        char *shared_name = "no name";
                   2093:
                   2094:        if (pool == NULL)
                   2095:                return;
                   2096:
                   2097:        /* get a pointer to the name if we have one */
                   2098:        if ((pool->shared_network != NULL) &&
                   2099:            (pool->shared_network->name != NULL)) {
                   2100:                shared_name = pool->shared_network->name;
                   2101:        }
                   2102:
                   2103:        count = pool->lease_count;
                   2104:        used = count - (pool->free_leases + pool->backup_leases);
                   2105:
                   2106:        /* The logged flag indicates if we have already crossed the high
                   2107:         * threshold and emitted a log message.  If it is set we check to
                   2108:         * see if we have re-crossed the low threshold and need to reset
                   2109:         * things.  When we cross the high threshold we determine what
                   2110:         * the low threshold is and save it into the low_threshold value.
                   2111:         * When we cross that threshold we reset the logged flag and
                   2112:         * the low_threshold to 0 which allows the high threshold message
                   2113:         * to be emitted once again.
                   2114:         * if we haven't recrossed the boundry we don't need to do anything.
                   2115:         */
                   2116:        if (pool->logged !=0) {
                   2117:                if (used <= pool->low_threshold) {
                   2118:                        pool->low_threshold = 0;
                   2119:                        pool->logged = 0;
                   2120:                        log_error("Pool threshold reset - shared subnet: %s; "
                   2121:                                  "address: %s; low threshold %d/%d.",
                   2122:                                  shared_name, piaddr(lease->ip_addr),
                   2123:                                  used, count);
                   2124:                }
                   2125:                return;
                   2126:        }
                   2127:
                   2128:        /* find the high threshold */
                   2129:        if (get_option_int(&poolhigh, &server_universe, packet, lease,  NULL,
                   2130:                           packet->options, state->options, state->options,
                   2131:                           &lease->scope, SV_LOG_THRESHOLD_HIGH, MDL) == 0) {
                   2132:                /* no threshold bail out */
                   2133:                return;
                   2134:        }
                   2135:
                   2136:        /* We do have a threshold for this pool, see if its valid */
                   2137:        if ((poolhigh <= 0) || (poolhigh > 100)) {
                   2138:                /* not valid */
                   2139:                return;
                   2140:        }
                   2141:
                   2142:        /* we have a valid value, have we exceeded it */
                   2143:        high_threshold = FIND_PERCENT(count, poolhigh);
                   2144:        if (used < high_threshold) {
                   2145:                /* nope, no more to do */
                   2146:                return;
                   2147:        }
                   2148:
                   2149:        /* we've exceeded it, output a message */
                   2150:        log_error("Pool threshold exceeded - shared subnet: %s; "
                   2151:                  "address: %s; high threshold %d%% %d/%d.",
                   2152:                  shared_name, piaddr(lease->ip_addr),
                   2153:                  poolhigh, used, count);
                   2154:
                   2155:        /* handle the low threshold now, if we don't
                   2156:         * have a valid one we default to 0. */
                   2157:        if ((get_option_int(&poollow, &server_universe, packet, lease,  NULL,
                   2158:                            packet->options, state->options, state->options,
                   2159:                            &lease->scope, SV_LOG_THRESHOLD_LOW, MDL) == 0) ||
                   2160:            (poollow > 100)) {
                   2161:                poollow = 0;
                   2162:        }
                   2163:
                   2164:        /*
                   2165:         * If the low theshold is higher than the high threshold we continue to log
                   2166:         * If it isn't then we set the flag saying we already logged and determine
                   2167:         * what the reset threshold is.
                   2168:         */
                   2169:        if (poollow < poolhigh) {
                   2170:                pool->logged = 1;
                   2171:                pool->low_threshold = FIND_PERCENT(count, poollow);
                   2172:        }
                   2173: }
                   2174:
                   2175: void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                   2176:        struct packet *packet;
                   2177:        struct lease *lease;
                   2178:        unsigned int offer;
                   2179:        TIME when;
                   2180:        char *msg;
                   2181:        int ms_nulltp;
                   2182:        struct host_decl *hp;
                   2183: {
                   2184:        struct lease *lt;
                   2185:        struct lease_state *state;
                   2186:        struct lease *next;
                   2187:        struct host_decl *host = (struct host_decl *)0;
                   2188:        TIME lease_time;
                   2189:        TIME offered_lease_time;
                   2190:        struct data_string d1;
                   2191:        TIME min_lease_time;
                   2192:        TIME max_lease_time;
                   2193:        TIME default_lease_time;
                   2194:        struct option_cache *oc;
                   2195:        isc_result_t result;
1.1.1.2   christos 2196:        TIME original_cltt;
1.1       christos 2197:        struct in_addr from;
                   2198:        TIME remaining_time;
                   2199:        struct iaddr cip;
                   2200: #if defined(DELAYED_ACK)
                   2201:        /* By default we don't do the enqueue */
                   2202:        isc_boolean_t enqueue = ISC_FALSE;
                   2203: #endif
                   2204:        int use_old_lease = 0;
1.1.1.2   christos 2205:        int same_client = 0;
1.1       christos 2206:
                   2207:        unsigned i, j;
                   2208:        int s1;
                   2209:        int ignorep;
                   2210:
                   2211:        /* If we're already acking this lease, don't do it again. */
                   2212:        if (lease -> state)
                   2213:                return;
                   2214:
                   2215:        /* Save original cltt for comparison later. */
1.1.1.2   christos 2216:        original_cltt = lease->cltt;
1.1       christos 2217:
                   2218:        /* If the lease carries a host record, remember it. */
                   2219:        if (hp)
                   2220:                host_reference (&host, hp, MDL);
                   2221:        else if (lease -> host)
                   2222:                host_reference (&host, lease -> host, MDL);
                   2223:
                   2224:        /* Allocate a lease state structure... */
                   2225:        state = new_lease_state (MDL);
                   2226:        if (!state)
                   2227:                log_fatal ("unable to allocate lease state!");
                   2228:        state -> got_requested_address = packet -> got_requested_address;
                   2229:        shared_network_reference (&state -> shared_network,
                   2230:                                  packet -> interface -> shared_network, MDL);
                   2231:
                   2232:        /* See if we got a server identifier option. */
                   2233:        if (lookup_option (&dhcp_universe,
                   2234:                           packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
                   2235:                state -> got_server_identifier = 1;
                   2236:
                   2237:        maybe_return_agent_options(packet, state->options);
                   2238:
                   2239:        /* If we are offering a lease that is still currently valid, preserve
                   2240:           the events.  We need to do this because if the client does not
                   2241:           REQUEST our offer, it will expire in 2 minutes, overriding the
                   2242:           expire time in the currently in force lease.  We want the expire
                   2243:           events to be executed at that point. */
                   2244:        if (lease->ends <= cur_time && offer != DHCPOFFER) {
                   2245:                /* Get rid of any old expiry or release statements - by
                   2246:                   executing the statements below, we will be inserting new
                   2247:                   ones if there are any to insert. */
                   2248:                if (lease->on_star.on_expiry)
                   2249:                        executable_statement_dereference
                   2250:                                (&lease->on_star.on_expiry, MDL);
                   2251:                if (lease->on_star.on_commit)
                   2252:                        executable_statement_dereference
                   2253:                                (&lease->on_star.on_commit, MDL);
                   2254:                if (lease->on_star.on_release)
                   2255:                        executable_statement_dereference
                   2256:                                (&lease->on_star.on_release, MDL);
                   2257:        }
                   2258:
                   2259:        /* Execute statements in scope starting with the subnet scope. */
                   2260:        execute_statements_in_scope (NULL, packet, lease,
                   2261:                                     NULL, packet->options,
                   2262:                                     state->options, &lease->scope,
                   2263:                                     lease->subnet->group, NULL, NULL);
                   2264:
                   2265:        /* If the lease is from a pool, run the pool scope. */
                   2266:        if (lease->pool)
                   2267:                (execute_statements_in_scope(NULL, packet, lease, NULL,
                   2268:                                             packet->options, state->options,
                   2269:                                             &lease->scope, lease->pool->group,
                   2270:                                             lease->pool->
                   2271:                                                shared_network->group,
                   2272:                                             NULL));
                   2273:
                   2274:        /* Execute statements from class scopes. */
                   2275:        for (i = packet -> class_count; i > 0; i--) {
                   2276:                execute_statements_in_scope(NULL, packet, lease, NULL,
                   2277:                                            packet->options, state->options,
                   2278:                                            &lease->scope,
                   2279:                                            packet->classes[i - 1]->group,
                   2280:                                            (lease->pool ? lease->pool->group
                   2281:                                             : lease->subnet->group),
                   2282:                                            NULL);
                   2283:        }
                   2284:
                   2285:        /* See if the client is only supposed to have one lease at a time,
                   2286:           and if so, find its other leases and release them.    We can only
                   2287:           do this on DHCPREQUEST.    It's a little weird to do this before
                   2288:           looking at permissions, because the client might not actually
                   2289:           _get_ a lease after we've done the permission check, but the
                   2290:           assumption for this option is that the client has exactly one
                   2291:           network interface, and will only ever remember one lease.   So
                   2292:           if it sends a DHCPREQUEST, and doesn't get the lease, it's already
                   2293:           forgotten about its old lease, so we can too. */
                   2294:        if (packet -> packet_type == DHCPREQUEST &&
                   2295:            (oc = lookup_option (&server_universe, state -> options,
                   2296:                                 SV_ONE_LEASE_PER_CLIENT)) &&
                   2297:            evaluate_boolean_option_cache (&ignorep,
                   2298:                                           packet, lease,
                   2299:                                           (struct client_state *)0,
                   2300:                                           packet -> options,
                   2301:                                           state -> options, &lease -> scope,
                   2302:                                           oc, MDL)) {
                   2303:            struct lease *seek;
                   2304:            if (lease -> uid_len) {
                   2305:                do {
                   2306:                    seek = (struct lease *)0;
                   2307:                    find_lease_by_uid (&seek, lease -> uid,
                   2308:                                       lease -> uid_len, MDL);
                   2309:                    if (!seek)
                   2310:                        break;
                   2311:                    if (seek == lease && !seek -> n_uid) {
                   2312:                        lease_dereference (&seek, MDL);
                   2313:                        break;
                   2314:                    }
                   2315:                    next = (struct lease *)0;
                   2316:
                   2317:                    /* Don't release expired leases, and don't
                   2318:                       release the lease we're going to assign. */
                   2319:                    next = (struct lease *)0;
                   2320:                    while (seek) {
                   2321:                        if (seek -> n_uid)
                   2322:                            lease_reference (&next, seek -> n_uid, MDL);
                   2323:                        if (seek != lease &&
                   2324:                            seek -> binding_state != FTS_RELEASED &&
                   2325:                            seek -> binding_state != FTS_EXPIRED &&
                   2326:                            seek -> binding_state != FTS_RESET &&
                   2327:                            seek -> binding_state != FTS_FREE &&
                   2328:                            seek -> binding_state != FTS_BACKUP)
                   2329:                                break;
                   2330:                        lease_dereference (&seek, MDL);
                   2331:                        if (next) {
                   2332:                            lease_reference (&seek, next, MDL);
                   2333:                            lease_dereference (&next, MDL);
                   2334:                        }
                   2335:                    }
                   2336:                    if (next)
                   2337:                        lease_dereference (&next, MDL);
                   2338:                    if (seek) {
                   2339:                        release_lease (seek, packet);
                   2340:                        lease_dereference (&seek, MDL);
                   2341:                    } else
                   2342:                        break;
                   2343:                } while (1);
                   2344:            }
                   2345:            if (!lease -> uid_len ||
                   2346:                (host &&
                   2347:                 !host -> client_identifier.len &&
                   2348:                 (oc = lookup_option (&server_universe, state -> options,
                   2349:                                      SV_DUPLICATES)) &&
                   2350:                 !evaluate_boolean_option_cache (&ignorep, packet, lease,
                   2351:                                                 (struct client_state *)0,
                   2352:                                                 packet -> options,
                   2353:                                                 state -> options,
                   2354:                                                 &lease -> scope,
                   2355:                                                 oc, MDL))) {
                   2356:                do {
                   2357:                    seek = (struct lease *)0;
                   2358:                    find_lease_by_hw_addr
                   2359:                            (&seek, lease -> hardware_addr.hbuf,
                   2360:                             lease -> hardware_addr.hlen, MDL);
                   2361:                    if (!seek)
                   2362:                            break;
                   2363:                    if (seek == lease && !seek -> n_hw) {
                   2364:                            lease_dereference (&seek, MDL);
                   2365:                            break;
                   2366:                    }
                   2367:                    next = (struct lease *)0;
                   2368:                    while (seek) {
                   2369:                        if (seek -> n_hw)
                   2370:                            lease_reference (&next, seek -> n_hw, MDL);
                   2371:                        if (seek != lease &&
                   2372:                            seek -> binding_state != FTS_RELEASED &&
                   2373:                            seek -> binding_state != FTS_EXPIRED &&
                   2374:                            seek -> binding_state != FTS_RESET &&
                   2375:                            seek -> binding_state != FTS_FREE &&
                   2376:                            seek -> binding_state != FTS_BACKUP)
                   2377:                                break;
                   2378:                        lease_dereference (&seek, MDL);
                   2379:                        if (next) {
                   2380:                            lease_reference (&seek, next, MDL);
                   2381:                            lease_dereference (&next, MDL);
                   2382:                        }
                   2383:                    }
                   2384:                    if (next)
                   2385:                        lease_dereference (&next, MDL);
                   2386:                    if (seek) {
                   2387:                        release_lease (seek, packet);
                   2388:                        lease_dereference (&seek, MDL);
                   2389:                    } else
                   2390:                        break;
                   2391:                } while (1);
                   2392:            }
                   2393:        }
1.1.1.2   christos 2394:
1.1       christos 2395:
                   2396:        /* Make sure this packet satisfies the configured minimum
                   2397:           number of seconds. */
                   2398:        memset (&d1, 0, sizeof d1);
                   2399:        if (offer == DHCPOFFER &&
                   2400:            (oc = lookup_option (&server_universe, state -> options,
                   2401:                                 SV_MIN_SECS))) {
                   2402:                if (evaluate_option_cache (&d1, packet, lease,
                   2403:                                           (struct client_state *)0,
                   2404:                                           packet -> options, state -> options,
                   2405:                                           &lease -> scope, oc, MDL)) {
                   2406:                        if (d1.len &&
                   2407:                            ntohs (packet -> raw -> secs) < d1.data [0]) {
                   2408:                                log_info("%s: configured min-secs value (%d) "
                   2409:                                         "is greater than secs field (%d).  "
                   2410:                                         "message dropped.", msg, d1.data[0],
                   2411:                                         ntohs(packet->raw->secs));
                   2412:                                data_string_forget (&d1, MDL);
                   2413:                                free_lease_state (state, MDL);
                   2414:                                if (host)
                   2415:                                        host_dereference (&host, MDL);
                   2416:                                return;
                   2417:                        }
                   2418:                        data_string_forget (&d1, MDL);
                   2419:                }
                   2420:        }
                   2421:
                   2422:        /* Try to find a matching host declaration for this lease.
                   2423:         */
                   2424:        if (!host) {
                   2425:                struct host_decl *hp = (struct host_decl *)0;
                   2426:                struct host_decl *h;
                   2427:
                   2428:                /* Try to find a host_decl that matches the client
                   2429:                   identifier or hardware address on the packet, and
                   2430:                   has no fixed IP address.   If there is one, hang
                   2431:                   it off the lease so that its option definitions
                   2432:                   can be used. */
                   2433:                oc = lookup_option (&dhcp_universe, packet -> options,
                   2434:                                    DHO_DHCP_CLIENT_IDENTIFIER);
                   2435:                if (oc &&
                   2436:                    evaluate_option_cache (&d1, packet, lease,
                   2437:                                           (struct client_state *)0,
                   2438:                                           packet -> options, state -> options,
                   2439:                                           &lease -> scope, oc, MDL)) {
                   2440:                        find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
                   2441:                        data_string_forget (&d1, MDL);
                   2442:                        for (h = hp; h; h = h -> n_ipaddr) {
                   2443:                                if (!h -> fixed_addr)
                   2444:                                        break;
                   2445:                        }
                   2446:                        if (h)
                   2447:                                host_reference (&host, h, MDL);
                   2448:                        if (hp != NULL)
                   2449:                                host_dereference(&hp, MDL);
                   2450:                }
                   2451:                if (!host) {
                   2452:                        find_hosts_by_haddr (&hp,
                   2453:                                             packet -> raw -> htype,
                   2454:                                             packet -> raw -> chaddr,
                   2455:                                             packet -> raw -> hlen,
                   2456:                                             MDL);
                   2457:                        for (h = hp; h; h = h -> n_ipaddr) {
                   2458:                                if (!h -> fixed_addr)
                   2459:                                        break;
                   2460:                        }
                   2461:                        if (h)
                   2462:                                host_reference (&host, h, MDL);
                   2463:                        if (hp != NULL)
                   2464:                                host_dereference(&hp, MDL);
                   2465:                }
                   2466:                if (!host) {
                   2467:                        find_hosts_by_option(&hp, packet,
                   2468:                                             packet->options, MDL);
                   2469:                        for (h = hp; h; h = h -> n_ipaddr) {
                   2470:                                if (!h -> fixed_addr)
                   2471:                                        break;
                   2472:                        }
                   2473:                        if (h)
                   2474:                                host_reference (&host, h, MDL);
                   2475:                        if (hp != NULL)
                   2476:                                host_dereference(&hp, MDL);
                   2477:                }
                   2478:        }
                   2479:
                   2480:        /* If we have a host_decl structure, run the options associated
                   2481:           with its group.  Whether the host decl struct is old or not. */
                   2482:        if (host)
                   2483:                execute_statements_in_scope (NULL, packet, lease, NULL,
                   2484:                                             packet->options, state->options,
                   2485:                                             &lease->scope, host->group,
                   2486:                                             (lease->pool
                   2487:                                              ? lease->pool->group
                   2488:                                              : lease->subnet->group),
                   2489:                                             NULL);
                   2490:
                   2491:        /* Drop the request if it's not allowed for this client.   By
                   2492:           default, unknown clients are allowed. */
                   2493:        if (!host &&
                   2494:            (oc = lookup_option (&server_universe, state -> options,
                   2495:                                 SV_BOOT_UNKNOWN_CLIENTS)) &&
                   2496:            !evaluate_boolean_option_cache (&ignorep,
                   2497:                                            packet, lease,
                   2498:                                            (struct client_state *)0,
                   2499:                                            packet -> options,
                   2500:                                            state -> options,
                   2501:                                            &lease -> scope, oc, MDL)) {
                   2502:                if (!ignorep)
                   2503:                        log_info ("%s: unknown client", msg);
                   2504:                free_lease_state (state, MDL);
                   2505:                if (host)
                   2506:                        host_dereference (&host, MDL);
                   2507:                return;
1.1.1.2   christos 2508:        }
1.1       christos 2509:
                   2510:        /* Drop the request if it's not allowed for this client. */
                   2511:        if (!offer &&
                   2512:            (oc = lookup_option (&server_universe, state -> options,
                   2513:                                   SV_ALLOW_BOOTP)) &&
                   2514:            !evaluate_boolean_option_cache (&ignorep,
                   2515:                                            packet, lease,
                   2516:                                            (struct client_state *)0,
                   2517:                                            packet -> options,
                   2518:                                            state -> options,
                   2519:                                            &lease -> scope, oc, MDL)) {
                   2520:                if (!ignorep)
                   2521:                        log_info ("%s: bootp disallowed", msg);
                   2522:                free_lease_state (state, MDL);
                   2523:                if (host)
                   2524:                        host_dereference (&host, MDL);
                   2525:                return;
1.1.1.2   christos 2526:        }
1.1       christos 2527:
                   2528:        /* Drop the request if booting is specifically denied. */
                   2529:        oc = lookup_option (&server_universe, state -> options,
                   2530:                            SV_ALLOW_BOOTING);
                   2531:        if (oc &&
                   2532:            !evaluate_boolean_option_cache (&ignorep,
                   2533:                                            packet, lease,
                   2534:                                            (struct client_state *)0,
                   2535:                                            packet -> options,
                   2536:                                            state -> options,
                   2537:                                            &lease -> scope, oc, MDL)) {
                   2538:                if (!ignorep)
                   2539:                        log_info ("%s: booting disallowed", msg);
                   2540:                free_lease_state (state, MDL);
                   2541:                if (host)
                   2542:                        host_dereference (&host, MDL);
                   2543:                return;
                   2544:        }
                   2545:
                   2546:        /* If we are configured to do per-class billing, do it. */
                   2547:        if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
                   2548:                /* See if the lease is currently being billed to a
                   2549:                   class, and if so, whether or not it can continue to
                   2550:                   be billed to that class. */
                   2551:                if (lease -> billing_class) {
                   2552:                        for (i = 0; i < packet -> class_count; i++)
                   2553:                                if (packet -> classes [i] ==
                   2554:                                    lease -> billing_class)
                   2555:                                        break;
                   2556:                        if (i == packet -> class_count) {
                   2557:                                unbill_class(lease);
                   2558:                                /* Active lease billing change negates reuse */
                   2559:                                if (lease->binding_state == FTS_ACTIVE) {
                   2560:                                        lease->cannot_reuse = 1;
                   2561:                                }
                   2562:                        }
                   2563:                }
                   2564:
                   2565:                /* If we don't have an active billing, see if we need
                   2566:                   one, and if we do, try to do so. */
                   2567:                if (lease->billing_class == NULL) {
                   2568:                        char *cname = "";
                   2569:                        int bill = 0;
                   2570:
                   2571:                        for (i = 0; i < packet->class_count; i++) {
1.1.1.2   christos 2572:                                struct class *billclass, *superclass;
1.1       christos 2573:
                   2574:                                billclass = packet->classes[i];
                   2575:                                if (billclass->lease_limit) {
                   2576:                                        bill++;
                   2577:                                        if (bill_class(lease, billclass))
                   2578:                                                break;
                   2579:
1.1.1.2   christos 2580:                                        superclass = billclass->superclass;
                   2581:                                        if (superclass != NULL)
                   2582:                                                cname = superclass->name;
1.1       christos 2583:                                        else
                   2584:                                                cname = billclass->name;
                   2585:                                }
                   2586:                        }
                   2587:                        if (bill != 0 && i == packet->class_count) {
                   2588:                                log_info("%s: no available billing: lease "
                   2589:                                         "limit reached in all matching "
                   2590:                                         "classes (last: '%s')", msg, cname);
                   2591:                                free_lease_state(state, MDL);
                   2592:                                if (host)
                   2593:                                        host_dereference(&host, MDL);
                   2594:                                return;
                   2595:                        }
                   2596:
                   2597:                        /*
                   2598:                         * If this is an offer, undo the billing.  We go
                   2599:                         * through all the steps above to bill a class so
                   2600:                         * we can hit the 'no available billing' mark and
                   2601:                         * abort without offering.  But it just doesn't make
                   2602:                         * sense to permanently bill a class for a non-active
                   2603:                         * lease.  This means on REQUEST, we will bill this
                   2604:                         * lease again (if there is a REQUEST).
                   2605:                         */
                   2606:                        if (offer == DHCPOFFER &&
                   2607:                            lease->billing_class != NULL &&
                   2608:                            lease->binding_state != FTS_ACTIVE)
                   2609:                                unbill_class(lease);
                   2610:
                   2611:                        /* Lease billing change negates reuse */
                   2612:                        if (lease->billing_class != NULL) {
                   2613:                                lease->cannot_reuse = 1;
                   2614:                        }
                   2615:                }
                   2616:        }
                   2617:
                   2618:        /* Figure out the filename. */
                   2619:        oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
                   2620:        if (oc)
                   2621:                evaluate_option_cache (&state -> filename, packet, lease,
                   2622:                                       (struct client_state *)0,
                   2623:                                       packet -> options, state -> options,
                   2624:                                       &lease -> scope, oc, MDL);
                   2625:
                   2626:        /* Choose a server name as above. */
                   2627:        oc = lookup_option (&server_universe, state -> options,
                   2628:                            SV_SERVER_NAME);
                   2629:        if (oc)
                   2630:                evaluate_option_cache (&state -> server_name, packet, lease,
                   2631:                                       (struct client_state *)0,
                   2632:                                       packet -> options, state -> options,
                   2633:                                       &lease -> scope, oc, MDL);
                   2634:
                   2635:        /* At this point, we have a lease that we can offer the client.
                   2636:           Now we construct a lease structure that contains what we want,
                   2637:           and call supersede_lease to do the right thing with it. */
                   2638:        lt = (struct lease *)0;
                   2639:        result = lease_allocate (&lt, MDL);
                   2640:        if (result != ISC_R_SUCCESS) {
                   2641:                log_info ("%s: can't allocate temporary lease structure: %s",
                   2642:                          msg, isc_result_totext (result));
                   2643:                free_lease_state (state, MDL);
                   2644:                if (host)
                   2645:                        host_dereference (&host, MDL);
                   2646:                return;
                   2647:        }
1.1.1.2   christos 2648:
1.1       christos 2649:        /* Use the ip address of the lease that we finally found in
                   2650:           the database. */
                   2651:        lt -> ip_addr = lease -> ip_addr;
                   2652:
                   2653:        /* Start now. */
                   2654:        lt -> starts = cur_time;
                   2655:
                   2656:        /* Figure out how long a lease to assign.    If this is a
                   2657:           dynamic BOOTP lease, its duration must be infinite. */
                   2658:        if (offer) {
                   2659:                lt->flags &= ~BOOTP_LEASE;
                   2660:
                   2661:                default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
                   2662:                if ((oc = lookup_option (&server_universe, state -> options,
                   2663:                                         SV_DEFAULT_LEASE_TIME))) {
                   2664:                        if (evaluate_option_cache (&d1, packet, lease,
                   2665:                                                   (struct client_state *)0,
                   2666:                                                   packet -> options,
                   2667:                                                   state -> options,
                   2668:                                                   &lease -> scope, oc, MDL)) {
                   2669:                                if (d1.len == sizeof (u_int32_t))
                   2670:                                        default_lease_time =
                   2671:                                                getULong (d1.data);
                   2672:                                data_string_forget (&d1, MDL);
                   2673:                        }
                   2674:                }
                   2675:
                   2676:                if ((oc = lookup_option (&dhcp_universe, packet -> options,
                   2677:                                         DHO_DHCP_LEASE_TIME)))
                   2678:                        s1 = evaluate_option_cache (&d1, packet, lease,
                   2679:                                                    (struct client_state *)0,
                   2680:                                                    packet -> options,
                   2681:                                                    state -> options,
                   2682:                                                    &lease -> scope, oc, MDL);
                   2683:                else
                   2684:                        s1 = 0;
                   2685:
                   2686:                if (s1 && (d1.len == 4)) {
                   2687:                        u_int32_t ones = 0xffffffff;
                   2688:
                   2689:                        /* One potential use of reserved leases is to allow
                   2690:                         * clients to signal reservation of their lease.  They
                   2691:                         * can kinda sorta do this, if you squint hard enough,
                   2692:                         * by supplying an 'infinite' requested-lease-time
                   2693:                         * option.  This is generally bad practice...you want
                   2694:                         * clients to return to the server on at least some
                   2695:                         * period (days, months, years) to get up-to-date
                   2696:                         * config state.  So;
                   2697:                         *
                   2698:                         * 1) A client requests 0xffffffff lease-time.
                   2699:                         * 2) The server reserves the lease, and assigns a
                   2700:                         *    <= max_lease_time lease-time to the client, which
                   2701:                         *    we presume is much smaller than 0xffffffff.
                   2702:                         * 3) The client ultimately fails to renew its lease
                   2703:                         *    (all clients go offline at some point).
                   2704:                         * 4) The server retains the reservation, although
                   2705:                         *    the lease expires and passes through those states
                   2706:                         *    as normal, it's placed in the 'reserved' queue,
                   2707:                         *    and is under no circumstances allocated to any
                   2708:                         *    clients.
                   2709:                         *
                   2710:                         * Whether the client knows its reserving its lease or
                   2711:                         * not, this can be a handy tool for a sysadmin.
                   2712:                         */
                   2713:                        if ((memcmp(d1.data, &ones, 4) == 0) &&
                   2714:                            (oc = lookup_option(&server_universe,
                   2715:                                                state->options,
                   2716:                                                SV_RESERVE_INFINITE)) &&
                   2717:                            evaluate_boolean_option_cache(&ignorep, packet,
                   2718:                                                lease, NULL, packet->options,
                   2719:                                                state->options, &lease->scope,
                   2720:                                                oc, MDL)) {
                   2721:                                lt->flags |= RESERVED_LEASE;
                   2722:                                if (!ignorep)
                   2723:                                        log_info("Infinite-leasetime "
                   2724:                                                 "reservation made on %s.",
                   2725:                                                 piaddr(lt->ip_addr));
                   2726:                        }
                   2727:
                   2728:                        lease_time = getULong (d1.data);
                   2729:                } else
                   2730:                        lease_time = default_lease_time;
                   2731:
                   2732:                if (s1)
                   2733:                        data_string_forget(&d1, MDL);
                   2734:
                   2735:                /* See if there's a maximum lease time. */
                   2736:                max_lease_time = DEFAULT_MAX_LEASE_TIME;
                   2737:                if ((oc = lookup_option (&server_universe, state -> options,
                   2738:                                         SV_MAX_LEASE_TIME))) {
                   2739:                        if (evaluate_option_cache (&d1, packet, lease,
                   2740:                                                   (struct client_state *)0,
                   2741:                                                   packet -> options,
                   2742:                                                   state -> options,
                   2743:                                                   &lease -> scope, oc, MDL)) {
                   2744:                                if (d1.len == sizeof (u_int32_t))
                   2745:                                        max_lease_time =
                   2746:                                                getULong (d1.data);
                   2747:                                data_string_forget (&d1, MDL);
                   2748:                        }
                   2749:                }
                   2750:
                   2751:                /* Enforce the maximum lease length. */
                   2752:                if (lease_time < 0 /* XXX */
                   2753:                    || lease_time > max_lease_time)
                   2754:                        lease_time = max_lease_time;
1.1.1.2   christos 2755:
1.1       christos 2756:                min_lease_time = DEFAULT_MIN_LEASE_TIME;
                   2757:                if (min_lease_time > max_lease_time)
                   2758:                        min_lease_time = max_lease_time;
                   2759:
                   2760:                if ((oc = lookup_option (&server_universe, state -> options,
                   2761:                                         SV_MIN_LEASE_TIME))) {
                   2762:                        if (evaluate_option_cache (&d1, packet, lease,
                   2763:                                                   (struct client_state *)0,
                   2764:                                                   packet -> options,
                   2765:                                                   state -> options,
                   2766:                                                   &lease -> scope, oc, MDL)) {
                   2767:                                if (d1.len == sizeof (u_int32_t))
                   2768:                                        min_lease_time = getULong (d1.data);
                   2769:                                data_string_forget (&d1, MDL);
                   2770:                        }
                   2771:                }
                   2772:
                   2773:                /* CC: If there are less than
                   2774:                   adaptive-lease-time-threshold % free leases,
                   2775:                     hand out only short term leases */
                   2776:
                   2777:                memset(&d1, 0, sizeof(d1));
                   2778:                if (lease->pool &&
                   2779:                    (oc = lookup_option(&server_universe, state->options,
                   2780:                                        SV_ADAPTIVE_LEASE_TIME_THRESHOLD)) &&
                   2781:                    evaluate_option_cache(&d1, packet, lease, NULL,
                   2782:                                          packet->options, state->options,
                   2783:                                          &lease->scope, oc, MDL)) {
                   2784:                        if (d1.len == 1 && d1.data[0] > 0 &&
                   2785:                            d1.data[0] < 100) {
                   2786:                                TIME adaptive_time;
                   2787:                                int poolfilled, total, count;
                   2788:
                   2789:                                if (min_lease_time)
                   2790:                                        adaptive_time = min_lease_time;
                   2791:                                else
                   2792:                                        adaptive_time = DEFAULT_MIN_LEASE_TIME;
                   2793:
                   2794:                                /* Allow the client to keep its lease. */
                   2795:                                if (lease->ends - cur_time > adaptive_time)
                   2796:                                        adaptive_time = lease->ends - cur_time;
                   2797:
                   2798:                                count = lease->pool->lease_count;
                   2799:                                total = count - (lease->pool->free_leases +
                   2800:                                                 lease->pool->backup_leases);
                   2801:
                   2802:                                poolfilled = (total > (INT_MAX / 100)) ?
                   2803:                                             total / (count / 100) :
                   2804:                                             (total * 100) / count;
                   2805:
                   2806:                                log_debug("Adap-lease: Total: %d, Free: %d, "
                   2807:                                          "Ends: %d, Adaptive: %d, Fill: %d, "
                   2808:                                          "Threshold: %d",
                   2809:                                          lease->pool->lease_count,
                   2810:                                          lease->pool->free_leases,
                   2811:                                          (int)(lease->ends - cur_time),
                   2812:                                          (int)adaptive_time, poolfilled,
                   2813:                                          d1.data[0]);
                   2814:
                   2815:                                if (poolfilled >= d1.data[0] &&
                   2816:                                    lease_time > adaptive_time) {
                   2817:                                        log_info("Pool over threshold, time "
                   2818:                                                 "for %s reduced from %d to "
                   2819:                                                 "%d.", piaddr(lease->ip_addr),
                   2820:                                                 (int)lease_time,
                   2821:                                                 (int)adaptive_time);
                   2822:
                   2823:                                        lease_time = adaptive_time;
                   2824:                                }
                   2825:                        }
                   2826:                        data_string_forget(&d1, MDL);
                   2827:                }
                   2828:
                   2829:
                   2830:                /*
                   2831:                 * If this is an ack check to see if we have used enough of
                   2832:                 * the pool to want to log a message
                   2833:                 */
                   2834:                if (offer == DHCPACK)
                   2835:                        check_pool_threshold(packet, lease, state);
                   2836:
                   2837:                /* a client requests an address which is not yet active*/
1.1.1.2   christos 2838:                if (lease->pool && lease->pool->valid_from &&
1.1       christos 2839:                     cur_time < lease->pool->valid_from) {
                   2840:                        /* NAK leases before pool activation date */
                   2841:                        cip.len = 4;
                   2842:                        memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
                   2843:                        nak_lease(packet, &cip, lease->subnet->group);
                   2844:                        free_lease_state (state, MDL);
                   2845:                        lease_dereference (&lt, MDL);
                   2846:                        if (host)
                   2847:                                host_dereference (&host, MDL);
                   2848:                        return;
1.1.1.2   christos 2849:
1.1       christos 2850:                }
                   2851:
                   2852:                /* CC:
                   2853:                a) NAK current lease if past the expiration date
                   2854:                b) extend lease only up to the expiration date, but not
                   2855:                below min-lease-time
                   2856:                Setting min-lease-time is essential for this to work!
                   2857:                The value of min-lease-time determines the length
                   2858:                of the transition window:
                   2859:                A client renewing a second before the deadline will
                   2860:                get a min-lease-time lease. Since the current ip might not
                   2861:                be routable after the deadline, the client will
                   2862:                be offline until it DISCOVERS again. Otherwise it will
                   2863:                receive a NAK at T/2.
                   2864:                A min-lease-time of 6 seconds effectively switches over
                   2865:                all clients in this pool very quickly.
                   2866:                        */
1.1.1.2   christos 2867:
1.1       christos 2868:                if (lease->pool && lease->pool->valid_until) {
                   2869:                        if (cur_time >= lease->pool->valid_until) {
                   2870:                                /* NAK leases after pool expiration date */
                   2871:                                cip.len = 4;
                   2872:                                memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
                   2873:                                nak_lease(packet, &cip, lease->subnet->group);
                   2874:                                free_lease_state (state, MDL);
                   2875:                                lease_dereference (&lt, MDL);
                   2876:                                if (host)
                   2877:                                        host_dereference (&host, MDL);
                   2878:                                return;
                   2879:                        }
                   2880:                        remaining_time = lease->pool->valid_until - cur_time;
                   2881:                        if (lease_time > remaining_time)
                   2882:                                lease_time = remaining_time;
                   2883:                }
1.1.1.2   christos 2884:
1.1       christos 2885:                if (lease_time < min_lease_time) {
                   2886:                        if (min_lease_time)
                   2887:                                lease_time = min_lease_time;
                   2888:                        else
                   2889:                                lease_time = default_lease_time;
                   2890:                }
                   2891:
                   2892:
                   2893: #if defined (FAILOVER_PROTOCOL)
                   2894:                /* Okay, we know the lease duration.   Now check the
                   2895:                   failover state, if any. */
                   2896:                if (lease -> pool && lease -> pool -> failover_peer) {
                   2897:                        TIME new_lease_time = lease_time;
                   2898:                        dhcp_failover_state_t *peer =
                   2899:                            lease -> pool -> failover_peer;
                   2900:
                   2901:                        /* Copy previous lease failover ack-state. */
                   2902:                        lt->tsfp = lease->tsfp;
                   2903:                        lt->atsfp = lease->atsfp;
                   2904:
                   2905:                        /* cltt set below */
                   2906:
                   2907:                        /* Lease times less than MCLT are not a concern. */
                   2908:                        if (lease_time > peer->mclt) {
                   2909:                                /* Each server can only offer a lease time
                   2910:                                 * that is either equal to MCLT (at least),
                   2911:                                 * or up to TSFP+MCLT.  Only if the desired
                   2912:                                 * lease time falls within TSFP+MCLT, can
                   2913:                                 * the server allow it.
                   2914:                                 */
                   2915:                                if (lt->tsfp <= cur_time)
                   2916:                                        new_lease_time = peer->mclt;
                   2917:                                else if ((cur_time + lease_time) >
                   2918:                                         (lt->tsfp + peer->mclt))
                   2919:                                        new_lease_time = (lt->tsfp - cur_time)
                   2920:                                                                + peer->mclt;
                   2921:                        }
                   2922:
                   2923:                        /* Update potential expiry.  Allow for the desired
                   2924:                         * lease time plus one half the actual (whether
                   2925:                         * modified downward or not) lease time, which is
                   2926:                         * actually an estimate of when the client will
                   2927:                         * renew.  This way, the client will be able to get
                   2928:                         * the desired lease time upon renewal.
                   2929:                         */
                   2930:                        if (offer == DHCPACK) {
                   2931:                                if (lease_time == INFINITE_TIME) {
                   2932:                                        lt->tstp = MAX_TIME;
                   2933:                                } else {
                   2934:                                        lt->tstp =
                   2935:                                                leaseTimeCheck(
                   2936:                                                    (cur_time + lease_time
                   2937:                                                     + (new_lease_time / 2)),
                   2938:                                                    MAX_TIME - 1);
                   2939:                                }
                   2940:
                   2941:                                /* If we reduced the potential expiry time,
                   2942:                                 * make sure we don't offer an old-expiry-time
                   2943:                                 * lease for this lease before the change is
                   2944:                                 * ack'd.
                   2945:                                 */
                   2946:                                if (lt->tstp < lt->tsfp)
                   2947:                                        lt->tsfp = lt->tstp;
                   2948:                        } else
                   2949:                                lt->tstp = lease->tstp;
                   2950:
                   2951:                        /* Use failover-modified lease time.  */
                   2952:                        lease_time = new_lease_time;
                   2953:                }
                   2954: #endif /* FAILOVER_PROTOCOL */
                   2955:
                   2956:                if (lease_time == INFINITE_TIME) {
                   2957:                        state->offered_expiry = MAX_TIME;
                   2958:                } else {
                   2959:                        /* If the lease duration causes the time value to wrap,
                   2960:                         use the maximum expiry time. */
                   2961:                        state->offered_expiry
                   2962:                                = leaseTimeCheck(cur_time + lease_time,
                   2963:                                                 MAX_TIME - 1);
                   2964:                }
                   2965:
                   2966:                if (when)
                   2967:                        lt -> ends = when;
                   2968:                else
                   2969:                        lt -> ends = state -> offered_expiry;
                   2970:
                   2971:                /* Don't make lease active until we actually get a
                   2972:                   DHCPREQUEST. */
                   2973:                if (offer == DHCPACK)
                   2974:                        lt -> next_binding_state = FTS_ACTIVE;
                   2975:                else
                   2976:                        lt -> next_binding_state = lease -> binding_state;
                   2977:        } else {
                   2978:                lt->flags |= BOOTP_LEASE;
                   2979:
                   2980:                lease_time = MAX_TIME - cur_time;
                   2981:
                   2982:                if ((oc = lookup_option (&server_universe, state -> options,
                   2983:                                         SV_BOOTP_LEASE_LENGTH))) {
                   2984:                        if (evaluate_option_cache (&d1, packet, lease,
                   2985:                                                   (struct client_state *)0,
                   2986:                                                   packet -> options,
                   2987:                                                   state -> options,
                   2988:                                                   &lease -> scope, oc, MDL)) {
                   2989:                                if (d1.len == sizeof (u_int32_t))
                   2990:                                        lease_time = getULong (d1.data);
                   2991:                                data_string_forget (&d1, MDL);
                   2992:                        }
                   2993:                }
                   2994:
                   2995:                if ((oc = lookup_option (&server_universe, state -> options,
                   2996:                                         SV_BOOTP_LEASE_CUTOFF))) {
                   2997:                        if (evaluate_option_cache (&d1, packet, lease,
                   2998:                                                   (struct client_state *)0,
                   2999:                                                   packet -> options,
                   3000:                                                   state -> options,
                   3001:                                                   &lease -> scope, oc, MDL)) {
                   3002:                                if (d1.len == sizeof (u_int32_t))
                   3003:                                        lease_time = (getULong (d1.data) -
                   3004:                                                      cur_time);
                   3005:                                data_string_forget (&d1, MDL);
                   3006:                        }
                   3007:                }
                   3008:
                   3009:                lt -> ends = state -> offered_expiry = cur_time + lease_time;
                   3010:                lt -> next_binding_state = FTS_ACTIVE;
                   3011:        }
                   3012:
                   3013:        /* Update Client Last Transaction Time. */
                   3014:        lt->cltt = cur_time;
                   3015:
                   3016:        /* See if we want to record the uid for this client */
                   3017:        oc = lookup_option(&server_universe, state->options,
                   3018:                           SV_IGNORE_CLIENT_UIDS);
                   3019:        if ((oc == NULL) ||
                   3020:            !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
                   3021:                                           packet->options, state->options,
                   3022:                                           &lease->scope, oc, MDL)) {
1.1.1.2   christos 3023:
1.1       christos 3024:                /* Record the uid, if given... */
                   3025:                oc = lookup_option (&dhcp_universe, packet -> options,
                   3026:                                    DHO_DHCP_CLIENT_IDENTIFIER);
                   3027:                if (oc &&
                   3028:                    evaluate_option_cache(&d1, packet, lease, NULL,
                   3029:                                          packet->options, state->options,
                   3030:                                          &lease->scope, oc, MDL)) {
                   3031:                        if (d1.len <= sizeof(lt->uid_buf)) {
                   3032:                                memcpy(lt->uid_buf, d1.data, d1.len);
                   3033:                                lt->uid = lt->uid_buf;
                   3034:                                lt->uid_max = sizeof(lt->uid_buf);
                   3035:                                lt->uid_len = d1.len;
                   3036:                        } else {
                   3037:                                unsigned char *tuid;
                   3038:                                lt->uid_max = d1.len;
                   3039:                                lt->uid_len = d1.len;
                   3040:                                tuid = (unsigned char *)dmalloc(lt->uid_max,
                   3041:                                                                MDL);
                   3042:                                /* XXX inelegant */
                   3043:                                if (!tuid)
                   3044:                                        log_fatal ("no memory for large uid.");
                   3045:                                memcpy(tuid, d1.data, lt->uid_len);
                   3046:                                lt->uid = tuid;
                   3047:                        }
                   3048:                        data_string_forget (&d1, MDL);
                   3049:                }
                   3050:        }
                   3051:
                   3052:        if (host) {
                   3053:                host_reference (&lt -> host, host, MDL);
                   3054:                host_dereference (&host, MDL);
                   3055:        }
                   3056:        if (lease -> subnet)
                   3057:                subnet_reference (&lt -> subnet, lease -> subnet, MDL);
                   3058:        if (lease -> billing_class)
                   3059:                class_reference (&lt -> billing_class,
                   3060:                                 lease -> billing_class, MDL);
                   3061:
                   3062:        /* Set a flag if this client is a broken client that NUL
                   3063:           terminates string options and expects us to do likewise. */
                   3064:        if (ms_nulltp)
                   3065:                lease -> flags |= MS_NULL_TERMINATION;
                   3066:        else
                   3067:                lease -> flags &= ~MS_NULL_TERMINATION;
                   3068:
                   3069:        /* Save any bindings. */
                   3070:        if (lease -> scope) {
                   3071:                binding_scope_reference (&lt -> scope, lease -> scope, MDL);
                   3072:                binding_scope_dereference (&lease -> scope, MDL);
                   3073:        }
                   3074:        if (lease -> agent_options)
                   3075:                option_chain_head_reference (&lt -> agent_options,
                   3076:                                             lease -> agent_options, MDL);
                   3077:
                   3078:        /* Save the vendor-class-identifier for DHCPLEASEQUERY. */
                   3079:        oc = lookup_option(&dhcp_universe, packet->options,
                   3080:                           DHO_VENDOR_CLASS_IDENTIFIER);
                   3081:        if (oc != NULL &&
                   3082:            evaluate_option_cache(&d1, packet, NULL, NULL, packet->options,
                   3083:                                  NULL, &lt->scope, oc, MDL)) {
                   3084:                if (d1.len != 0) {
                   3085:                        bind_ds_value(&lt->scope, "vendor-class-identifier",
                   3086:                                      &d1);
                   3087:                }
                   3088:
                   3089:                data_string_forget(&d1, MDL);
                   3090:        }
                   3091:
                   3092:        /* If we got relay agent information options from the packet, then
                   3093:         * cache them for renewal in case the relay agent can't supply them
                   3094:         * when the client unicasts.  The options may be from an addressed
                   3095:         * "l3" relay, or from an unaddressed "l2" relay which does not set
                   3096:         * giaddr.
                   3097:         */
                   3098:        if (!packet->agent_options_stashed &&
                   3099:            (packet->options != NULL) &&
                   3100:            packet->options->universe_count > agent_universe.index &&
                   3101:            packet->options->universes[agent_universe.index] != NULL) {
                   3102:            oc = lookup_option (&server_universe, state -> options,
                   3103:                                SV_STASH_AGENT_OPTIONS);
                   3104:            if (!oc ||
                   3105:                evaluate_boolean_option_cache (&ignorep, packet, lease,
                   3106:                                               (struct client_state *)0,
                   3107:                                               packet -> options,
                   3108:                                               state -> options,
                   3109:                                               &lease -> scope, oc, MDL)) {
                   3110:                if (lt -> agent_options)
                   3111:                    option_chain_head_dereference (&lt -> agent_options, MDL);
                   3112:                option_chain_head_reference
                   3113:                        (&lt -> agent_options,
                   3114:                         (struct option_chain_head *)
                   3115:                         packet -> options -> universes [agent_universe.index],
                   3116:                         MDL);
                   3117:            }
                   3118:        }
                   3119:
                   3120:        /* Replace the old lease hostname with the new one, if it's changed. */
                   3121:        oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
                   3122:        if (oc)
                   3123:                s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
                   3124:                                            (struct client_state *)0,
                   3125:                                            packet -> options,
                   3126:                                            (struct option_state *)0,
                   3127:                                            &global_scope, oc, MDL);
                   3128:        else
                   3129:                s1 = 0;
                   3130:
                   3131:        if (oc && s1 &&
                   3132:            lease -> client_hostname &&
                   3133:            strlen (lease -> client_hostname) == d1.len &&
                   3134:            !memcmp (lease -> client_hostname, d1.data, d1.len)) {
                   3135:                /* Hasn't changed. */
                   3136:                data_string_forget (&d1, MDL);
                   3137:                lt -> client_hostname = lease -> client_hostname;
                   3138:                lease -> client_hostname = (char *)0;
                   3139:        } else if (oc && s1) {
                   3140:                lt -> client_hostname = dmalloc (d1.len + 1, MDL);
                   3141:                if (!lt -> client_hostname)
                   3142:                        log_error ("no memory for client hostname.");
                   3143:                else {
                   3144:                        memcpy (lt -> client_hostname, d1.data, d1.len);
                   3145:                        lt -> client_hostname [d1.len] = 0;
                   3146:                }
                   3147:                data_string_forget (&d1, MDL);
                   3148:                /* hostname changed, can't reuse lease */
                   3149:                lease->cannot_reuse = 1;
                   3150:        }
                   3151:
                   3152:        /* Record the hardware address, if given... */
                   3153:        lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
                   3154:        lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
                   3155:        memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
                   3156:                sizeof packet -> raw -> chaddr);
                   3157:
                   3158:        /*
                   3159:         * If client has requested the lease become infinite, then it
                   3160:         * doens't qualify for reuse even if it's younger than the
                   3161:         * dhcp-cache-threshold.
                   3162:         */
                   3163:        if ((lt->flags & RESERVED_LEASE) && !(lease->flags & RESERVED_LEASE)) {
                   3164:                log_debug ("Cannot reuse: lease is changing to RESERVED");
                   3165:                lease->cannot_reuse = 1;
                   3166:        }
                   3167:
                   3168:        lt->flags |= lease->flags & ~PERSISTENT_FLAGS;
                   3169:
                   3170:        /* If there are statements to execute when the lease is
                   3171:           committed, execute them. */
                   3172:        if (lease->on_star.on_commit && (!offer || offer == DHCPACK)) {
                   3173:                execute_statements (NULL, packet, lt, NULL, packet->options,
                   3174:                                    state->options, &lt->scope,
                   3175:                                    lease->on_star.on_commit, NULL);
                   3176:                if (lease->on_star.on_commit)
                   3177:                        executable_statement_dereference
                   3178:                                (&lease->on_star.on_commit, MDL);
                   3179:        }
                   3180:
                   3181: #ifdef NSUPDATE
                   3182:        /* Perform DDNS updates, if configured to. */
                   3183:        if ((!offer || offer == DHCPACK) &&
                   3184:            (!(oc = lookup_option (&server_universe, state -> options,
                   3185:                                   SV_DDNS_UPDATES)) ||
                   3186:             evaluate_boolean_option_cache (&ignorep, packet, lt,
                   3187:                                            (struct client_state *)0,
                   3188:                                            packet -> options,
                   3189:                                            state -> options,
                   3190:                                            &lt -> scope, oc, MDL))) {
                   3191:                ddns_updates(packet, lt, lease, NULL, NULL, state->options);
                   3192:        }
                   3193: #endif /* NSUPDATE */
                   3194:
                   3195:        /* Don't call supersede_lease on a mocked-up lease. */
                   3196:        if (lease -> flags & STATIC_LEASE) {
                   3197:                /* Copy the hardware address into the static lease
                   3198:                   structure. */
                   3199:                lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
                   3200:                lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
                   3201:                memcpy (&lease -> hardware_addr.hbuf [1],
                   3202:                        packet -> raw -> chaddr,
                   3203:                        sizeof packet -> raw -> chaddr); /* XXX */
                   3204:        } else {
                   3205:                int commit = (!offer || (offer == DHCPACK));
                   3206:
                   3207:                /* If dhcp-cache-threshold is enabled, see if "lease" can
                   3208:                 * be reused. */
1.1.1.2   christos 3209:                use_old_lease = reuse_lease(packet, lt, lease, state, offer,
                   3210:                                            &same_client);
1.1       christos 3211:                if (use_old_lease == 1) {
                   3212:                        commit = 0;
                   3213:                }
                   3214:
                   3215: #if !defined(DELAYED_ACK)
                   3216:                /* Install the new information on 'lt' onto the lease at
                   3217:                 * 'lease'.  If this is a DHCPOFFER, it is a 'soft' promise,
                   3218:                 * if it is a DHCPACK, it is a 'hard' binding, so it needs
                   3219:                 * to be recorded and propogated immediately.  If the update
                   3220:                 * fails, don't ACK it (or BOOTREPLY) either; we may give
                   3221:                 * the same lease to another client later, and that would be
                   3222:                 * a conflict.
                   3223:                 */
                   3224:                if ((use_old_lease == 0) &&
                   3225:                    !supersede_lease(lease, lt, commit,
                   3226:                                     offer == DHCPACK, offer == DHCPACK, 0)) {
                   3227: #else /* defined(DELAYED_ACK) */
                   3228:                /*
                   3229:                 * If there already isn't a need for a lease commit, and we
                   3230:                 * can just answer right away, set a flag to indicate this.
                   3231:                 */
                   3232:                if (commit)
                   3233:                        enqueue = ISC_TRUE;
                   3234:
                   3235:                /* Install the new information on 'lt' onto the lease at
                   3236:                 * 'lease'.  We will not 'commit' this information to disk
                   3237:                 * yet (fsync()), we will 'propogate' the information if
                   3238:                 * this is BOOTP or a DHCPACK, but we will not 'pimmediate'ly
                   3239:                 * transmit failover binding updates (this is delayed until
                   3240:                 * after the fsync()).  If the update fails, don't ACK it (or
                   3241:                 * BOOTREPLY either); we may give the same lease out to a
                   3242:                 * different client, and that would be a conflict.
                   3243:                 */
                   3244:                if ((use_old_lease == 0) &&
                   3245:                    !supersede_lease(lease, lt, 0,
                   3246:                                     !offer || offer == DHCPACK, 0, 0)) {
                   3247: #endif
                   3248:                        log_info ("%s: database update failed", msg);
                   3249:                        free_lease_state (state, MDL);
                   3250:                        lease_dereference (&lt, MDL);
                   3251:                        return;
                   3252:                }
                   3253:        }
                   3254:        lease_dereference (&lt, MDL);
                   3255:
                   3256:        /* Remember the interface on which the packet arrived. */
                   3257:        state -> ip = packet -> interface;
                   3258:
                   3259:        /* Remember the giaddr, xid, secs, flags and hops. */
                   3260:        state -> giaddr = packet -> raw -> giaddr;
                   3261:        state -> ciaddr = packet -> raw -> ciaddr;
                   3262:        state -> xid = packet -> raw -> xid;
                   3263:        state -> secs = packet -> raw -> secs;
                   3264:        state -> bootp_flags = packet -> raw -> flags;
                   3265:        state -> hops = packet -> raw -> hops;
                   3266:        state -> offer = offer;
                   3267:
                   3268:        /* If we're always supposed to broadcast to this client, set
                   3269:           the broadcast bit in the bootp flags field. */
                   3270:        if ((oc = lookup_option (&server_universe, state -> options,
                   3271:                                SV_ALWAYS_BROADCAST)) &&
                   3272:            evaluate_boolean_option_cache (&ignorep, packet, lease,
                   3273:                                           (struct client_state *)0,
                   3274:                                           packet -> options, state -> options,
                   3275:                                           &lease -> scope, oc, MDL))
                   3276:                state -> bootp_flags |= htons (BOOTP_BROADCAST);
                   3277:
                   3278:        /* Get the Maximum Message Size option from the packet, if one
                   3279:           was sent. */
                   3280:        oc = lookup_option (&dhcp_universe, packet -> options,
                   3281:                            DHO_DHCP_MAX_MESSAGE_SIZE);
                   3282:        if (oc &&
                   3283:            evaluate_option_cache (&d1, packet, lease,
                   3284:                                   (struct client_state *)0,
                   3285:                                   packet -> options, state -> options,
                   3286:                                   &lease -> scope, oc, MDL)) {
                   3287:                if (d1.len == sizeof (u_int16_t))
                   3288:                        state -> max_message_size = getUShort (d1.data);
                   3289:                data_string_forget (&d1, MDL);
                   3290:        } else {
                   3291:                oc = lookup_option (&dhcp_universe, state -> options,
                   3292:                                    DHO_DHCP_MAX_MESSAGE_SIZE);
                   3293:                if (oc &&
                   3294:                    evaluate_option_cache (&d1, packet, lease,
                   3295:                                           (struct client_state *)0,
                   3296:                                           packet -> options, state -> options,
                   3297:                                           &lease -> scope, oc, MDL)) {
                   3298:                        if (d1.len == sizeof (u_int16_t))
                   3299:                                state -> max_message_size =
                   3300:                                        getUShort (d1.data);
                   3301:                        data_string_forget (&d1, MDL);
                   3302:                }
                   3303:        }
                   3304:
                   3305:        /* Get the Subnet Selection option from the packet, if one
                   3306:           was sent. */
                   3307:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                   3308:                                 DHO_SUBNET_SELECTION))) {
                   3309:
                   3310:                /* Make a copy of the data. */
                   3311:                struct option_cache *noc = (struct option_cache *)0;
                   3312:                if (option_cache_allocate (&noc, MDL)) {
                   3313:                        if (oc -> data.len)
                   3314:                                data_string_copy (&noc -> data,
                   3315:                                                  &oc -> data, MDL);
                   3316:                        if (oc -> expression)
                   3317:                                expression_reference (&noc -> expression,
                   3318:                                                      oc -> expression, MDL);
                   3319:                        if (oc -> option)
                   3320:                                option_reference(&(noc->option), oc->option,
                   3321:                                                 MDL);
                   3322:
                   3323:                        save_option (&dhcp_universe, state -> options, noc);
                   3324:                        option_cache_dereference (&noc, MDL);
                   3325:                }
                   3326:        }
                   3327:
                   3328:        /* Now, if appropriate, put in DHCP-specific options that
                   3329:           override those. */
                   3330:        if (state -> offer) {
                   3331:                i = DHO_DHCP_MESSAGE_TYPE;
                   3332:                oc = (struct option_cache *)0;
                   3333:                if (option_cache_allocate (&oc, MDL)) {
                   3334:                        if (make_const_data (&oc -> expression,
                   3335:                                             &state -> offer, 1, 0, 0, MDL)) {
                   3336:                                option_code_hash_lookup(&oc->option,
                   3337:                                                        dhcp_universe.code_hash,
                   3338:                                                        &i, 0, MDL);
                   3339:                                save_option (&dhcp_universe,
                   3340:                                             state -> options, oc);
                   3341:                        }
                   3342:                        option_cache_dereference (&oc, MDL);
                   3343:                }
                   3344:
                   3345:                get_server_source_address(&from, state->options,
                   3346:                                          state->options, packet);
                   3347:                memcpy(state->from.iabuf, &from, sizeof(from));
                   3348:                state->from.len = sizeof(from);
                   3349:
                   3350:                offered_lease_time =
                   3351:                        state -> offered_expiry - cur_time;
                   3352:
                   3353:                putULong(state->expiry, (u_int32_t)offered_lease_time);
                   3354:                i = DHO_DHCP_LEASE_TIME;
                   3355:                oc = (struct option_cache *)0;
                   3356:                if (option_cache_allocate (&oc, MDL)) {
                   3357:                        if (make_const_data(&oc->expression, state->expiry,
                   3358:                                            4, 0, 0, MDL)) {
                   3359:                                option_code_hash_lookup(&oc->option,
                   3360:                                                        dhcp_universe.code_hash,
                   3361:                                                        &i, 0, MDL);
                   3362:                                save_option (&dhcp_universe,
                   3363:                                             state -> options, oc);
                   3364:                        }
                   3365:                        option_cache_dereference (&oc, MDL);
                   3366:                }
                   3367:
                   3368:                /*
                   3369:                 * Validate any configured renew or rebinding times against
                   3370:                 * the determined lease time.  Do rebinding first so that
                   3371:                 * the renew time can be validated against the rebind time.
                   3372:                 */
                   3373:                if ((oc = lookup_option(&dhcp_universe, state->options,
                   3374:                                        DHO_DHCP_REBINDING_TIME)) != NULL &&
                   3375:                    evaluate_option_cache(&d1, packet, lease, NULL,
                   3376:                                          packet->options, state->options,
                   3377:                                          &lease->scope, oc, MDL)) {
                   3378:                        TIME rebind_time = getULong(d1.data);
                   3379:
                   3380:                        /* Drop the configured (invalid) rebinding time. */
                   3381:                        if (rebind_time >= offered_lease_time)
                   3382:                                delete_option(&dhcp_universe, state->options,
                   3383:                                              DHO_DHCP_REBINDING_TIME);
                   3384:                        else /* XXX: variable is reused. */
                   3385:                                offered_lease_time = rebind_time;
                   3386:
                   3387:                        data_string_forget(&d1, MDL);
                   3388:                }
                   3389:
                   3390:                if ((oc = lookup_option(&dhcp_universe, state->options,
                   3391:                                        DHO_DHCP_RENEWAL_TIME)) != NULL &&
                   3392:                    evaluate_option_cache(&d1, packet, lease, NULL,
                   3393:                                          packet->options, state->options,
                   3394:                                          &lease->scope, oc, MDL)) {
                   3395:                        if (getULong(d1.data) >= offered_lease_time)
                   3396:                                delete_option(&dhcp_universe, state->options,
                   3397:                                              DHO_DHCP_RENEWAL_TIME);
                   3398:
                   3399:                        data_string_forget(&d1, MDL);
                   3400:                }
                   3401:        } else {
                   3402:                /* XXXSK: should we use get_server_source_address() here? */
                   3403:                if (state -> ip -> address_count) {
                   3404:                        state -> from.len =
                   3405:                                sizeof state -> ip -> addresses [0];
                   3406:                        memcpy (state -> from.iabuf,
                   3407:                                &state -> ip -> addresses [0],
                   3408:                                state -> from.len);
                   3409:                }
                   3410:        }
                   3411:
                   3412:        /* Figure out the address of the boot file server. */
                   3413:        memset (&state -> siaddr, 0, sizeof state -> siaddr);
                   3414:        if ((oc =
                   3415:             lookup_option (&server_universe,
                   3416:                            state -> options, SV_NEXT_SERVER))) {
                   3417:                if (evaluate_option_cache (&d1, packet, lease,
                   3418:                                           (struct client_state *)0,
                   3419:                                           packet -> options, state -> options,
                   3420:                                           &lease -> scope, oc, MDL)) {
                   3421:                        /* If there was more than one answer,
                   3422:                           take the first. */
                   3423:                        if (d1.len >= 4 && d1.data)
                   3424:                                memcpy (&state -> siaddr, d1.data, 4);
                   3425:                        data_string_forget (&d1, MDL);
                   3426:                }
                   3427:        }
                   3428:
                   3429:        /* Use the subnet mask from the subnet declaration if no other
                   3430:           mask has been provided. */
                   3431:        i = DHO_SUBNET_MASK;
                   3432:        if (!lookup_option (&dhcp_universe, state -> options, i)) {
                   3433:                oc = (struct option_cache *)0;
                   3434:                if (option_cache_allocate (&oc, MDL)) {
                   3435:                        if (make_const_data (&oc -> expression,
                   3436:                                             lease -> subnet -> netmask.iabuf,
                   3437:                                             lease -> subnet -> netmask.len,
                   3438:                                             0, 0, MDL)) {
                   3439:                                option_code_hash_lookup(&oc->option,
                   3440:                                                        dhcp_universe.code_hash,
                   3441:                                                        &i, 0, MDL);
                   3442:                                save_option (&dhcp_universe,
                   3443:                                             state -> options, oc);
                   3444:                        }
                   3445:                        option_cache_dereference (&oc, MDL);
                   3446:                }
                   3447:        }
                   3448:
                   3449:        /* Use the name of the host declaration if there is one
1.1.1.2   christos 3450:           and no hostname has otherwise been provided, and if the
1.1       christos 3451:           use-host-decl-name flag is set. */
                   3452:        use_host_decl_name(packet, lease, state->options);
                   3453:
                   3454:        /* Send client_id back if we received it and echo-client-id is on. */
                   3455:        echo_client_id(packet, lease, state->options, state->options);
                   3456:
                   3457:        /* If we don't have a hostname yet, and we've been asked to do
                   3458:           a reverse lookup to find the hostname, do it. */
                   3459:        i = DHO_HOST_NAME;
                   3460:        j = SV_GET_LEASE_HOSTNAMES;
                   3461:        if (!lookup_option(&dhcp_universe, state->options, i) &&
                   3462:            evaluate_boolean_option_cache
                   3463:             (&ignorep, packet, lease, NULL,
                   3464:              packet->options, state->options, &lease->scope,
                   3465:              lookup_option (&server_universe, state->options, j), MDL)) {
                   3466:                struct in_addr ia;
                   3467:                struct hostent *h;
1.1.1.2   christos 3468:
1.1       christos 3469:                memcpy (&ia, lease -> ip_addr.iabuf, 4);
1.1.1.2   christos 3470:
1.1       christos 3471:                h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
                   3472:                if (!h)
                   3473:                        log_error ("No hostname for %s", inet_ntoa (ia));
                   3474:                else {
                   3475:                        oc = (struct option_cache *)0;
                   3476:                        if (option_cache_allocate (&oc, MDL)) {
                   3477:                                if (make_const_data (&oc -> expression,
                   3478:                                                     ((unsigned char *)
                   3479:                                                      h -> h_name),
                   3480:                                                     strlen (h -> h_name) + 1,
                   3481:                                                     1, 1, MDL)) {
                   3482:                                        option_code_hash_lookup(&oc->option,
                   3483:                                                        dhcp_universe.code_hash,
                   3484:                                                                &i, 0, MDL);
                   3485:                                        save_option (&dhcp_universe,
                   3486:                                                     state -> options, oc);
                   3487:                                }
                   3488:                                option_cache_dereference (&oc, MDL);
                   3489:                        }
                   3490:                }
                   3491:        }
                   3492:
                   3493:        /* If so directed, use the leased IP address as the router address.
                   3494:           This supposedly makes Win95 machines ARP for all IP addresses,
                   3495:           so if the local router does proxy arp, you win. */
                   3496:
                   3497:        if (evaluate_boolean_option_cache
                   3498:            (&ignorep, packet, lease, (struct client_state *)0,
                   3499:             packet -> options, state -> options, &lease -> scope,
                   3500:             lookup_option (&server_universe, state -> options,
                   3501:                            SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
                   3502:                i = DHO_ROUTERS;
                   3503:                oc = lookup_option (&dhcp_universe, state -> options, i);
                   3504:                if (!oc) {
                   3505:                        oc = (struct option_cache *)0;
                   3506:                        if (option_cache_allocate (&oc, MDL)) {
                   3507:                                if (make_const_data (&oc -> expression,
                   3508:                                                     lease -> ip_addr.iabuf,
                   3509:                                                     lease -> ip_addr.len,
                   3510:                                                     0, 0, MDL)) {
                   3511:                                        option_code_hash_lookup(&oc->option,
                   3512:                                                        dhcp_universe.code_hash,
                   3513:                                                                &i, 0, MDL);
                   3514:                                        save_option (&dhcp_universe,
                   3515:                                                     state -> options, oc);
                   3516:                                }
1.1.1.2   christos 3517:                                option_cache_dereference (&oc, MDL);
1.1       christos 3518:                        }
                   3519:                }
                   3520:        }
                   3521:
                   3522:        /* If a site option space has been specified, use that for
                   3523:           site option codes. */
                   3524:        i = SV_SITE_OPTION_SPACE;
                   3525:        if ((oc = lookup_option (&server_universe, state -> options, i)) &&
                   3526:            evaluate_option_cache (&d1, packet, lease,
                   3527:                                   (struct client_state *)0,
                   3528:                                   packet -> options, state -> options,
                   3529:                                   &lease -> scope, oc, MDL)) {
                   3530:                struct universe *u = (struct universe *)0;
                   3531:
                   3532:                if (!universe_hash_lookup (&u, universe_hash,
                   3533:                                           (const char *)d1.data, d1.len,
                   3534:                                           MDL)) {
                   3535:                        log_error ("unknown option space %s.", d1.data);
1.1.1.2   christos 3536:                        data_string_forget (&d1, MDL);
1.1       christos 3537:                        return;
                   3538:                }
                   3539:
                   3540:                state -> options -> site_universe = u -> index;
                   3541:                state->options->site_code_min = find_min_site_code(u);
                   3542:                data_string_forget (&d1, MDL);
                   3543:        } else {
                   3544:                state -> options -> site_code_min = 0;
                   3545:                state -> options -> site_universe = dhcp_universe.index;
                   3546:        }
                   3547:
                   3548:        /* If the client has provided a list of options that it wishes
                   3549:           returned, use it to prioritize.  If there's a parameter
                   3550:           request list in scope, use that in preference.  Otherwise
                   3551:           use the default priority list. */
                   3552:
                   3553:        oc = lookup_option (&dhcp_universe, state -> options,
                   3554:                            DHO_DHCP_PARAMETER_REQUEST_LIST);
                   3555:
                   3556:        if (!oc)
                   3557:                oc = lookup_option (&dhcp_universe, packet -> options,
                   3558:                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
                   3559:        if (oc)
                   3560:                evaluate_option_cache (&state -> parameter_request_list,
                   3561:                                       packet, lease, (struct client_state *)0,
                   3562:                                       packet -> options, state -> options,
                   3563:                                       &lease -> scope, oc, MDL);
                   3564:
                   3565: #ifdef DEBUG_PACKET
                   3566:        dump_packet (packet);
                   3567:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
                   3568: #endif
                   3569:
                   3570:        lease -> state = state;
                   3571:
                   3572:        log_info ("%s", msg);
                   3573:
                   3574:        /* Hang the packet off the lease state. */
                   3575:        packet_reference (&lease -> state -> packet, packet, MDL);
                   3576:
1.1.1.2   christos 3577:        /* If this is a DHCPOFFER, send a ping (if appropriate) to the
                   3578:         * lease address before actually we send the offer. */
                   3579:        if ((offer == DHCPOFFER) &&
                   3580:            do_ping_check(packet, state, lease, original_cltt, same_client)) {
1.1       christos 3581:                ++outstanding_pings;
                   3582:        } else {
                   3583:                lease->cltt = cur_time;
                   3584: #if defined(DELAYED_ACK)
                   3585:                if (enqueue)
                   3586:                        delayed_ack_enqueue(lease);
1.1.1.2   christos 3587:                else
1.1       christos 3588: #endif
                   3589:                        dhcp_reply(lease);
                   3590:        }
                   3591: }
                   3592:
1.1.1.2   christos 3593: /*
                   3594:  * \brief Sends a ping to the lease ip_addr when appropriate
                   3595:  *
                   3596:  * A ping will be sent if all of the following are true:
                   3597:  *
                   3598:  * 1. Ping checks are enabled
                   3599:  * 2. The lease is neither active nor static
                   3600:  * 3. Any of the following is true:
                   3601:  *    a. The lease state is ABANDONED
                   3602:  *    b. This is the first offer of this lease (CLTT = 0)
                   3603:  *    c. The lease is being offered to a client other than its previous
                   3604:  *    owner
                   3605:  *    d. The lease is being offered to its previous owner and more than
                   3606:  *    cltt-secs have elapsed since CLTT of the original lease.
                   3607:  *
                   3608:  * \param packet inbound packet received from the client
                   3609:  * \param state lease options state
                   3610:  * \param lease lease to be offered (if one)
                   3611:  * \param original_cltt CLTT of the original lease
                   3612:  * \param same_client flag indicating if the client to be offered the
                   3613:  * lease is its previous owner
                   3614:  * \return Returns 1 if ping has been sent, 0 otherwise
                   3615:  */
                   3616: int do_ping_check(struct packet* packet, struct lease_state* state,
                   3617:                  struct lease* lease, TIME original_cltt,
                   3618:                  int same_client) {
                   3619:        TIME ping_timeout = DEFAULT_PING_TIMEOUT;
                   3620:        TIME ping_timeout_ms = DEFAULT_PING_TIMEOUT_MS;
                   3621:        struct option_cache *oc = NULL;
                   3622:        struct data_string ds;
                   3623:        struct timeval tv;
                   3624:        int ignorep;
                   3625:        int timeout_secs;
                   3626:        int timeout_ms;
                   3627:
                   3628:        // Don't go any further if lease is active or static.
                   3629:        if (lease->binding_state == FTS_ACTIVE || lease->flags & STATIC_LEASE) {
                   3630:                return (0);
                   3631:        }
                   3632:
                   3633:        // If pings aren't enabled, punt.
                   3634:        oc = lookup_option (&server_universe, state -> options, SV_PING_CHECKS);
                   3635:        if (oc &&
                   3636:            !(evaluate_boolean_option_cache (&ignorep, packet, lease,
                   3637:                                           0, packet->options, state->options,
                   3638:                                            &lease->scope, oc, MDL))) {
                   3639:                return (0);
                   3640:        }
                   3641:
                   3642:        // If it's not the first time for the same client and not an
                   3643:        // abandoned lease, we need to check the cltt threshold
                   3644:        if (same_client && original_cltt &&
                   3645:            lease->binding_state != FTS_ABANDONED) {
                   3646:                TIME cltt_secs = DEFAULT_PING_CLTT_SECS;
                   3647:                memset(&ds, 0, sizeof(ds));
                   3648:                oc = lookup_option (&server_universe, state->options,
                   3649:                                    SV_PING_CLTT_SECS);
                   3650:                if (oc &&
                   3651:                    (evaluate_option_cache (&ds, packet, lease, 0,
                   3652:                                            packet->options, state->options,
                   3653:                                            &lease->scope, oc, MDL))) {
                   3654:                        if (ds.len == sizeof (u_int32_t)) {
                   3655:                                cltt_secs = getULong (ds.data);
                   3656:                        }
                   3657:
                   3658:                        data_string_forget (&ds, MDL);
                   3659:                }
                   3660:
                   3661:                // Punt if it is too soon.
                   3662:                if (cur_time - original_cltt < cltt_secs) {
                   3663:                        return (0);
                   3664:                }
                   3665:        }
                   3666:
                   3667:        // Send the ping.
                   3668:        icmp_echorequest (&lease->ip_addr);
                   3669:
                   3670:        /* Determine whether to use configured or default ping timeout. */
                   3671:        memset(&ds, 0, sizeof(ds));
                   3672:
                   3673:        oc = lookup_option (&server_universe, state->options, SV_PING_TIMEOUT);
                   3674:        if (oc &&
                   3675:            (evaluate_option_cache (&ds, packet, lease, 0,
                   3676:                                    packet->options, state->options,
                   3677:                                    &lease->scope, oc, MDL))) {
                   3678:                if (ds.len == sizeof (u_int32_t)) {
                   3679:                        ping_timeout = getULong (ds.data);
                   3680:                }
                   3681:
                   3682:                data_string_forget (&ds, MDL);
                   3683:        }
                   3684:
                   3685:        oc = lookup_option (&server_universe, state->options, SV_PING_TIMEOUT_MS);
                   3686:        if (oc &&
                   3687:            (evaluate_option_cache (&ds, packet, lease, 0,
                   3688:                                    packet->options, state->options,
                   3689:                                    &lease->scope, oc, MDL))) {
                   3690:                if (ds.len == sizeof (u_int32_t)) {
                   3691:                        ping_timeout_ms = getULong (ds.data);
                   3692:                }
                   3693:
                   3694:                data_string_forget (&ds, MDL);
                   3695:        }
                   3696:
                   3697:        /*
                   3698:         * Set the timeout for the ping to the current timeval plus
                   3699:         * the configured time out. Use ping-timeout-ms if it is > 0.
                   3700:         * This overrides ping-timeout allowing users to specify it in
                   3701:         * milliseconds.
                   3702:        */
                   3703:        if (ping_timeout_ms > 0) {
                   3704:                timeout_secs = ping_timeout_ms / 1000;
                   3705:                timeout_ms = ping_timeout_ms % 1000;
                   3706:        } else {
                   3707:                timeout_secs = ping_timeout;
                   3708:                timeout_ms = 0;
                   3709:
                   3710:        }
                   3711:
                   3712:        tv.tv_sec = cur_tv.tv_sec + timeout_secs;
                   3713:        tv.tv_usec = cur_tv.tv_usec + (timeout_ms * 1000);
                   3714:
                   3715: #ifdef DEBUG
                   3716:        log_debug ("Pinging:%s, state: %d, same client? %s, "
                   3717:                   " orig_cltt %s, elasped: %ld, timeout in: %d.%d secs" ,
                   3718:                    piaddr(lease->ip_addr),
                   3719:                   lease->binding_state,
                   3720:                   (same_client ? "y" : "n"),
                   3721:                   (original_cltt ? print_time(original_cltt) : "0"),
                   3722:                   (original_cltt ? (long)(cur_time - original_cltt) : 0),
                   3723:                   timeout_secs, timeout_ms);
                   3724:
                   3725: #endif
                   3726:
                   3727:        add_timeout (&tv, lease_ping_timeout, lease, (tvref_t)lease_reference,
                   3728:                     (tvunref_t)lease_dereference);
                   3729:
                   3730:        return (1);
                   3731: }
                   3732:
                   3733:
1.1       christos 3734: #if defined(DELAYED_ACK)
                   3735:
                   3736: /*
                   3737:  * CC: queue single ACK:
                   3738:  * - write the lease (but do not fsync it yet)
                   3739:  * - add to double linked list
                   3740:  * - commit if more than xx ACKs pending
                   3741:  * - if necessary set the max timer and bump the next timer
                   3742:  *   but only up to the max timer value.
                   3743:  */
                   3744:
                   3745: static void
                   3746: delayed_ack_enqueue(struct lease *lease)
                   3747: {
                   3748:        struct leasequeue *q;
                   3749:
1.1.1.2   christos 3750:        if (!write_lease(lease))
1.1       christos 3751:                return;
                   3752:        if (free_ackqueue) {
                   3753:                q = free_ackqueue;
                   3754:                free_ackqueue = q->next;
                   3755:        } else {
                   3756:                q = ((struct leasequeue *)
                   3757:                             dmalloc(sizeof(struct leasequeue), MDL));
                   3758:                if (!q)
                   3759:                        log_fatal("delayed_ack_enqueue: no memory!");
                   3760:        }
                   3761:        memset(q, 0, sizeof *q);
                   3762:        /* prepend to ackqueue*/
                   3763:        lease_reference(&q->lease, lease, MDL);
                   3764:        q->next = ackqueue_head;
                   3765:        ackqueue_head = q;
1.1.1.2   christos 3766:        if (!ackqueue_tail)
1.1       christos 3767:                ackqueue_tail = q;
                   3768:        else
                   3769:                q->next->prev = q;
                   3770:
                   3771:        outstanding_acks++;
                   3772:        if (outstanding_acks > max_outstanding_acks) {
                   3773:                /* Cancel any pending timeout and call handler directly */
                   3774:                cancel_timeout(delayed_acks_timer, NULL);
                   3775:                delayed_acks_timer(NULL);
                   3776:        } else {
                   3777:                struct timeval next_fsync;
                   3778:
                   3779:                if (max_fsync.tv_sec == 0 && max_fsync.tv_usec == 0) {
                   3780:                        /* set the maximum time we'll wait */
                   3781:                        max_fsync.tv_sec = cur_tv.tv_sec + max_ack_delay_secs;
                   3782:                        max_fsync.tv_usec = cur_tv.tv_usec +
                   3783:                                max_ack_delay_usecs;
                   3784:
                   3785:                        if (max_fsync.tv_usec >= 1000000) {
                   3786:                                max_fsync.tv_sec++;
                   3787:                                max_fsync.tv_usec -= 1000000;
                   3788:                        }
                   3789:                }
                   3790:
                   3791:                /* Set the timeout */
                   3792:                next_fsync.tv_sec = cur_tv.tv_sec;
                   3793:                next_fsync.tv_usec = cur_tv.tv_usec + min_ack_delay_usecs;
                   3794:                if (next_fsync.tv_usec >= 1000000) {
                   3795:                        next_fsync.tv_sec++;
                   3796:                        next_fsync.tv_usec -= 1000000;
                   3797:                }
                   3798:                /* but not more than the max */
                   3799:                if ((next_fsync.tv_sec > max_fsync.tv_sec) ||
                   3800:                    ((next_fsync.tv_sec == max_fsync.tv_sec) &&
                   3801:                     (next_fsync.tv_usec > max_fsync.tv_usec))) {
                   3802:                        next_fsync.tv_sec = max_fsync.tv_sec;
                   3803:                        next_fsync.tv_usec = max_fsync.tv_usec;
                   3804:                }
                   3805:
                   3806:                add_timeout(&next_fsync, delayed_acks_timer, NULL,
                   3807:                            (tvref_t) NULL, (tvunref_t) NULL);
                   3808:        }
                   3809: }
                   3810:
                   3811: /* Processes any delayed acks:
                   3812:  * Commits the leases and then for each delayed ack:
                   3813:  *  - Update the failover peer if we're in failover
                   3814:  *  - Send the REPLY to the client
                   3815:  */
                   3816: static void
                   3817: delayed_acks_timer(void *foo)
                   3818: {
                   3819:        struct leasequeue *ack, *p;
                   3820:
                   3821:        /* Reset max fsync */
                   3822:        memset(&max_fsync, 0, sizeof(max_fsync));
                   3823:
                   3824:        if (!outstanding_acks) {
                   3825:                /* Nothing to do, so punt, shouldn't happen? */
                   3826:                return;
                   3827:        }
                   3828:
                   3829:        /* Commit the leases first */
                   3830:        commit_leases();
                   3831:
                   3832:        /* Now process the delayed ACKs
                   3833:         - update failover peer
                   3834:         - send out the ACK packets
                   3835:         - move the queue slots to the free list
                   3836:        */
                   3837:
                   3838:        /*  process from bottom to retain packet order */
1.1.1.2   christos 3839:        for (ack = ackqueue_tail ; ack ; ack = p) {
1.1       christos 3840:                p = ack->prev;
                   3841:
                   3842: #if defined(FAILOVER_PROTOCOL)
                   3843:                /* If we're in failover we need to send any deferred
                   3844:                * bind updates as well as the replies */
                   3845:                if (ack->lease->pool) {
                   3846:                        dhcp_failover_state_t *fpeer;
                   3847:
                   3848:                        fpeer = ack->lease->pool->failover_peer;
                   3849:                        if (fpeer && fpeer->link_to_peer) {
                   3850:                                dhcp_failover_send_updates(fpeer);
                   3851:                        }
                   3852:                }
                   3853: #endif
                   3854:
                   3855:                /* dhcp_reply() requires that the reply state still be valid */
                   3856:                if (ack->lease->state == NULL)
                   3857:                        log_error("delayed ack for %s has gone stale",
                   3858:                                  piaddr(ack->lease->ip_addr));
                   3859:                else {
                   3860:                        dhcp_reply(ack->lease);
                   3861:                }
                   3862:
                   3863:                lease_dereference(&ack->lease, MDL);
                   3864:                ack->next = free_ackqueue;
                   3865:                free_ackqueue = ack;
                   3866:        }
                   3867:
                   3868:        ackqueue_head = NULL;
                   3869:        ackqueue_tail = NULL;
                   3870:        outstanding_acks = 0;
                   3871: }
                   3872:
                   3873: #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
                   3874: void
                   3875: relinquish_ackqueue(void)
                   3876: {
                   3877:        struct leasequeue *q, *n;
1.1.1.2   christos 3878:
1.1       christos 3879:        for (q = ackqueue_head ; q ; q = n) {
                   3880:                n = q->next;
                   3881:                dfree(q, MDL);
                   3882:        }
                   3883:        for (q = free_ackqueue ; q ; q = n) {
                   3884:                n = q->next;
                   3885:                dfree(q, MDL);
                   3886:        }
                   3887: }
                   3888: #endif
                   3889:
                   3890: #endif /* defined(DELAYED_ACK) */
                   3891:
                   3892: void dhcp_reply (lease)
                   3893:        struct lease *lease;
                   3894: {
                   3895:        int bufs = 0;
                   3896:        unsigned packet_length;
                   3897:        struct dhcp_packet raw;
                   3898:        struct sockaddr_in to;
                   3899:        struct in_addr from;
                   3900:        struct hardware hto;
                   3901:        int result;
                   3902:        struct lease_state *state = lease -> state;
                   3903:        int nulltp, bootpp, unicastp = 1;
                   3904: #if defined(RELAY_PORT)
                   3905:        u_int16_t relay_port = 0;
                   3906: #endif
                   3907:        struct data_string d1;
                   3908:        const char *s;
                   3909:
                   3910:        if (!state)
                   3911:                log_fatal ("dhcp_reply was supplied lease with no state!");
                   3912:
                   3913:        /* Compose a response for the client... */
                   3914:        memset (&raw, 0, sizeof raw);
                   3915:        memset (&d1, 0, sizeof d1);
                   3916:
                   3917:        /* Copy in the filename if given; otherwise, flag the filename
                   3918:           buffer as available for options. */
                   3919:        if (state -> filename.len && state -> filename.data) {
                   3920:                memcpy (raw.file,
                   3921:                        state -> filename.data,
                   3922:                        state -> filename.len > sizeof raw.file
                   3923:                        ? sizeof raw.file : state -> filename.len);
                   3924:                if (sizeof raw.file > state -> filename.len)
                   3925:                        memset (&raw.file [state -> filename.len], 0,
                   3926:                                (sizeof raw.file) - state -> filename.len);
1.1.1.2   christos 3927:                else
1.1       christos 3928:                        log_info("file name longer than packet field "
1.1.1.2   christos 3929:                                 "truncated - field: %lu name: %d %.*s",
1.1       christos 3930:                                 (unsigned long)sizeof(raw.file),
                   3931:                                 state->filename.len, (int)state->filename.len,
                   3932:                                 state->filename.data);
                   3933:        } else
                   3934:                bufs |= 1;
                   3935:
                   3936:        /* Copy in the server name if given; otherwise, flag the
                   3937:           server_name buffer as available for options. */
                   3938:        if (state -> server_name.len && state -> server_name.data) {
                   3939:                memcpy (raw.sname,
                   3940:                        state -> server_name.data,
                   3941:                        state -> server_name.len > sizeof raw.sname
                   3942:                        ? sizeof raw.sname : state -> server_name.len);
                   3943:                if (sizeof raw.sname > state -> server_name.len)
                   3944:                        memset (&raw.sname [state -> server_name.len], 0,
                   3945:                                (sizeof raw.sname) - state -> server_name.len);
1.1.1.2   christos 3946:                else
1.1       christos 3947:                        log_info("server name longer than packet field "
1.1.1.2   christos 3948:                                 "truncated - field: %lu name: %d %.*s",
1.1       christos 3949:                                 (unsigned long)sizeof(raw.sname),
                   3950:                                 state->server_name.len,
                   3951:                                 (int)state->server_name.len,
                   3952:                                 state->server_name.data);
                   3953:        } else
                   3954:                bufs |= 2; /* XXX */
                   3955:
                   3956:        memcpy (raw.chaddr,
                   3957:                &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
                   3958:        raw.hlen = lease -> hardware_addr.hlen - 1;
                   3959:        raw.htype = lease -> hardware_addr.hbuf [0];
                   3960:
                   3961:        /* See if this is a Microsoft client that NUL-terminates its
                   3962:           strings and expects us to do likewise... */
                   3963:        if (lease -> flags & MS_NULL_TERMINATION)
                   3964:                nulltp = 1;
                   3965:        else
                   3966:                nulltp = 0;
                   3967:
                   3968:        /* See if this is a bootp client... */
                   3969:        if (state -> offer)
                   3970:                bootpp = 0;
                   3971:        else
                   3972:                bootpp = 1;
                   3973:
                   3974:        /* Insert such options as will fit into the buffer. */
                   3975:        packet_length = cons_options (state -> packet, &raw, lease,
                   3976:                                      (struct client_state *)0,
                   3977:                                      state -> max_message_size,
                   3978:                                      state -> packet -> options,
                   3979:                                      state -> options, &global_scope,
                   3980:                                      bufs, nulltp, bootpp,
                   3981:                                      &state -> parameter_request_list,
                   3982:                                      (char *)0);
                   3983:
                   3984:        memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
                   3985:        memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
                   3986:        raw.siaddr = state -> siaddr;
                   3987:        raw.giaddr = state -> giaddr;
                   3988:
                   3989:        raw.xid = state -> xid;
                   3990:        raw.secs = state -> secs;
                   3991:        raw.flags = state -> bootp_flags;
                   3992:        raw.hops = state -> hops;
                   3993:        raw.op = BOOTREPLY;
                   3994:
                   3995:        if (lease -> client_hostname) {
                   3996:                if ((strlen (lease -> client_hostname) <= 64) &&
                   3997:                    db_printable((unsigned char *)lease->client_hostname))
                   3998:                        s = lease -> client_hostname;
                   3999:                else
                   4000:                        s = "Hostname Unsuitable for Printing";
                   4001:        } else
                   4002:                s = (char *)0;
                   4003:
                   4004:        /* Make sure outgoing packets are at least as big
                   4005:           as a BOOTP packet. */
                   4006:        if (packet_length < BOOTP_MIN_LEN)
                   4007:                packet_length = BOOTP_MIN_LEN;
                   4008:
                   4009: #if defined(DHCPv6) && defined(DHCP4o6)
                   4010:        if (dhcpv4_over_dhcpv6 && (state->packet->dhcp4o6_response != NULL)) {
                   4011:                /* Say what we're doing... */
                   4012:                log_info ("DHCP4o6 %s on %s to %s %s%s%svia %s",
                   4013:                          (state -> offer
                   4014:                           ? (state -> offer == DHCPACK
                   4015:                              ? "DHCPACK" : "DHCPOFFER")
                   4016:                           : "BOOTREPLY"),
                   4017:                          piaddr (lease -> ip_addr),
                   4018:                          (lease -> hardware_addr.hlen
                   4019:                           ? print_hw_addr (lease -> hardware_addr.hbuf [0],
                   4020:                                            lease -> hardware_addr.hlen - 1,
                   4021:                                            &lease -> hardware_addr.hbuf [1])
                   4022:                           : print_hex_1(lease->uid_len, lease->uid, 60)),
                   4023:                          s ? "(" : "", s ? s : "", s ? ") " : "",
                   4024:                          piaddr(state->packet->client_addr));
                   4025:
                   4026:                /* fill dhcp4o6_response */
                   4027:                state->packet->dhcp4o6_response->len = packet_length;
                   4028:                state->packet->dhcp4o6_response->buffer = NULL;
                   4029:                if (!buffer_allocate(&state->packet->dhcp4o6_response->buffer,
                   4030:                                     packet_length, MDL)) {
                   4031:                        log_fatal("No memory to store DHCP4o6 reply.");
                   4032:                }
                   4033:                state->packet->dhcp4o6_response->data =
                   4034:                        state->packet->dhcp4o6_response->buffer->data;
                   4035:                memcpy(state->packet->dhcp4o6_response->buffer->data,
                   4036:                       &raw, packet_length);
                   4037:
                   4038:                /* done */
                   4039:                free_lease_state (state, MDL);
                   4040:                lease -> state = (struct lease_state *)0;
                   4041:
                   4042:                return;
                   4043:        }
                   4044: #endif
                   4045:
                   4046:        /* Say what we're doing... */
                   4047:        log_info ("%s on %s to %s %s%s%svia %s",
                   4048:                  (state -> offer
                   4049:                   ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
                   4050:                   : "BOOTREPLY"),
                   4051:                  piaddr (lease -> ip_addr),
                   4052:                  (lease -> hardware_addr.hlen
                   4053:                   ? print_hw_addr (lease -> hardware_addr.hbuf [0],
                   4054:                                    lease -> hardware_addr.hlen - 1,
                   4055:                                    &lease -> hardware_addr.hbuf [1])
                   4056:                   : print_hex_1(lease->uid_len, lease->uid, 60)),
                   4057:                  s ? "(" : "", s ? s : "", s ? ") " : "",
                   4058:                  (state -> giaddr.s_addr
                   4059:                   ? inet_ntoa (state -> giaddr)
                   4060:                   : state -> ip -> name));
                   4061:
                   4062: #ifdef DEBUG_PACKET
                   4063:        dump_raw ((unsigned char *)&raw, packet_length);
                   4064: #endif
                   4065:
                   4066:        /* Set up the hardware address... */
                   4067:        hto.hlen = lease -> hardware_addr.hlen;
                   4068:        memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
                   4069:
                   4070:        to.sin_family = AF_INET;
                   4071: #ifdef HAVE_SA_LEN
                   4072:        to.sin_len = sizeof to;
                   4073: #endif
                   4074:        memset (to.sin_zero, 0, sizeof to.sin_zero);
                   4075:
                   4076: #if defined(RELAY_PORT)
                   4077:        relay_port = dhcp_check_relayport(state->packet);
                   4078: #endif
                   4079:
                   4080:        /* If this was gatewayed, send it back to the gateway... */
                   4081:        if (raw.giaddr.s_addr) {
                   4082:                to.sin_addr = raw.giaddr;
                   4083:                if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
                   4084: #if defined(RELAY_PORT)
                   4085:                        to.sin_port = relay_port ? relay_port : local_port;
                   4086: #else
                   4087:                        to.sin_port = local_port;
                   4088: #endif
                   4089:                else
                   4090:                        to.sin_port = remote_port; /* For debugging. */
                   4091:
                   4092:                if (fallback_interface) {
                   4093:                        result = send_packet(fallback_interface, NULL, &raw,
                   4094:                                             packet_length, raw.siaddr, &to,
                   4095:                                             NULL);
                   4096:                        if (result < 0) {
                   4097:                                log_error ("%s:%d: Failed to send %d byte long "
                   4098:                                           "packet over %s interface.", MDL,
                   4099:                                           packet_length,
                   4100:                                           fallback_interface->name);
                   4101:                        }
                   4102:
                   4103:
                   4104:                        free_lease_state (state, MDL);
                   4105:                        lease -> state = (struct lease_state *)0;
                   4106:                        return;
                   4107:                }
                   4108:
                   4109:        /* If the client is RENEWING, unicast to the client using the
                   4110:           regular IP stack.  Some clients, particularly those that
                   4111:           follow RFC1541, are buggy, and send both ciaddr and server
                   4112:           identifier.  We deal with this situation by assuming that
                   4113:           if we got both dhcp-server-identifier and ciaddr, and
                   4114:           giaddr was not set, then the client is on the local
                   4115:           network, and we can therefore unicast or broadcast to it
                   4116:           successfully.  A client in REQUESTING state on another
                   4117:           network that's making this mistake will have set giaddr,
                   4118:           and will therefore get a relayed response from the above
                   4119:           code. */
                   4120:        } else if (raw.ciaddr.s_addr &&
                   4121:                   !((state -> got_server_identifier ||
                   4122:                      (raw.flags & htons (BOOTP_BROADCAST))) &&
                   4123:                     /* XXX This won't work if giaddr isn't zero, but it is: */
                   4124:                     (state -> shared_network ==
                   4125:                      lease -> subnet -> shared_network)) &&
                   4126:                   state -> offer == DHCPACK) {
                   4127:                to.sin_addr = raw.ciaddr;
                   4128:                to.sin_port = remote_port;
                   4129:
                   4130:                if (fallback_interface) {
                   4131:                        result = send_packet(fallback_interface, NULL, &raw,
                   4132:                                             packet_length, raw.siaddr, &to,
                   4133:                                             NULL);
                   4134:                        if (result < 0) {
                   4135:                                log_error("%s:%d: Failed to send %d byte long"
                   4136:                                          " packet over %s interface.", MDL,
                   4137:                                           packet_length,
                   4138:                                           fallback_interface->name);
                   4139:                        }
                   4140:
                   4141:                        free_lease_state (state, MDL);
                   4142:                        lease -> state = (struct lease_state *)0;
                   4143:                        return;
                   4144:                }
                   4145:
                   4146:        /* If it comes from a client that already knows its address
                   4147:           and is not requesting a broadcast response, and we can
                   4148:           unicast to a client without using the ARP protocol, sent it
                   4149:           directly to that client. */
                   4150:        } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
                   4151:                   can_unicast_without_arp (state -> ip)) {
                   4152:                to.sin_addr = raw.yiaddr;
                   4153:                to.sin_port = remote_port;
                   4154:
                   4155:        /* Otherwise, broadcast it on the local network. */
                   4156:        } else {
                   4157:                to.sin_addr = limited_broadcast;
                   4158:                to.sin_port = remote_port;
                   4159:                if (!(lease -> flags & UNICAST_BROADCAST_HACK))
                   4160:                        unicastp = 0;
                   4161:        }
                   4162:
                   4163:        memcpy (&from, state -> from.iabuf, sizeof from);
                   4164:
                   4165:        result = send_packet(state->ip, NULL, &raw, packet_length,
                   4166:                              from, &to, unicastp ? &hto : NULL);
                   4167:        if (result < 0) {
                   4168:            log_error ("%s:%d: Failed to send %d byte long "
                   4169:                       "packet over %s interface.", MDL,
                   4170:                       packet_length, state->ip->name);
                   4171:        }
                   4172:
                   4173:
                   4174:        /* Free all of the entries in the option_state structure
                   4175:           now that we're done with them. */
                   4176:
                   4177:        free_lease_state (state, MDL);
                   4178:        lease -> state = (struct lease_state *)0;
                   4179: }
                   4180:
                   4181: int find_lease (struct lease **lp,
                   4182:                struct packet *packet, struct shared_network *share, int *ours,
                   4183:                int *peer_has_leases, struct lease *ip_lease_in,
                   4184:                const char *file, int line)
                   4185: {
                   4186:        struct lease *uid_lease = (struct lease *)0;
                   4187:        struct lease *ip_lease = (struct lease *)0;
                   4188:        struct lease *hw_lease = (struct lease *)0;
                   4189:        struct lease *lease = (struct lease *)0;
                   4190:        struct iaddr cip;
                   4191:        struct host_decl *hp = (struct host_decl *)0;
                   4192:        struct host_decl *host = (struct host_decl *)0;
                   4193:        struct lease *fixed_lease = (struct lease *)0;
                   4194:        struct lease *next = (struct lease *)0;
                   4195:        struct option_cache *oc;
                   4196:        struct data_string d1;
                   4197:        int have_client_identifier = 0;
                   4198:        struct data_string client_identifier;
                   4199:        struct hardware h;
                   4200:
                   4201: #if defined(FAILOVER_PROTOCOL)
                   4202:        /* Quick check to see if the peer has leases. */
                   4203:        if (peer_has_leases) {
                   4204:                struct pool *pool;
                   4205:
                   4206:                for (pool = share->pools ; pool ; pool = pool->next) {
                   4207:                        dhcp_failover_state_t *peer = pool->failover_peer;
                   4208:
                   4209:                        if (peer &&
                   4210:                            ((peer->i_am == primary && pool->backup_leases) ||
                   4211:                             (peer->i_am == secondary && pool->free_leases))) {
                   4212:                                *peer_has_leases = 1;
                   4213:                                break;
                   4214:                        }
                   4215:                }
                   4216:        }
                   4217: #endif /* FAILOVER_PROTOCOL */
                   4218:
                   4219:        if (packet -> raw -> ciaddr.s_addr) {
                   4220:                cip.len = 4;
                   4221:                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
                   4222:        } else {
                   4223:                /* Look up the requested address. */
                   4224:                oc = lookup_option (&dhcp_universe, packet -> options,
                   4225:                                    DHO_DHCP_REQUESTED_ADDRESS);
                   4226:                memset (&d1, 0, sizeof d1);
                   4227:                if (oc &&
                   4228:                    evaluate_option_cache (&d1, packet, (struct lease *)0,
                   4229:                                           (struct client_state *)0,
                   4230:                                           packet -> options,
                   4231:                                           (struct option_state *)0,
                   4232:                                           &global_scope, oc, MDL)) {
                   4233:                        packet -> got_requested_address = 1;
                   4234:                        cip.len = 4;
                   4235:                        memcpy (cip.iabuf, d1.data, cip.len);
                   4236:                        data_string_forget (&d1, MDL);
1.1.1.2   christos 4237:                } else
1.1       christos 4238:                        cip.len = 0;
                   4239:        }
                   4240:
                   4241:        /* Try to find a host or lease that's been assigned to the
                   4242:           specified unique client identifier. */
                   4243:        oc = lookup_option (&dhcp_universe, packet -> options,
                   4244:                            DHO_DHCP_CLIENT_IDENTIFIER);
                   4245:        memset (&client_identifier, 0, sizeof client_identifier);
                   4246:        if (oc &&
                   4247:            evaluate_option_cache (&client_identifier,
                   4248:                                   packet, (struct lease *)0,
                   4249:                                   (struct client_state *)0,
                   4250:                                   packet -> options, (struct option_state *)0,
                   4251:                                   &global_scope, oc, MDL)) {
                   4252:                /* Remember this for later. */
                   4253:                have_client_identifier = 1;
                   4254:
                   4255:                /* First, try to find a fixed host entry for the specified
                   4256:                   client identifier... */
                   4257:                if (find_hosts_by_uid (&hp, client_identifier.data,
                   4258:                                       client_identifier.len, MDL)) {
                   4259:                        /* Remember if we know of this client. */
                   4260:                        packet -> known = 1;
                   4261:                        mockup_lease (&fixed_lease, packet, share, hp);
                   4262:                }
                   4263:
                   4264: #if defined (DEBUG_FIND_LEASE)
                   4265:                if (fixed_lease) {
                   4266:                        log_info ("Found host for client identifier: %s.",
                   4267:                              piaddr (fixed_lease -> ip_addr));
                   4268:                }
                   4269: #endif
                   4270:                if (hp) {
                   4271:                        if (!fixed_lease) /* Save the host if we found one. */
                   4272:                                host_reference (&host, hp, MDL);
                   4273:                        host_dereference (&hp, MDL);
                   4274:                }
                   4275:
                   4276:                find_lease_by_uid (&uid_lease, client_identifier.data,
                   4277:                                   client_identifier.len, MDL);
                   4278:        }
                   4279:
                   4280:        /* If we didn't find a fixed lease using the uid, try doing
                   4281:           it with the hardware address... */
                   4282:        if (!fixed_lease && !host) {
                   4283:                if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
                   4284:                                         packet -> raw -> chaddr,
                   4285:                                         packet -> raw -> hlen, MDL)) {
                   4286:                        /* Remember if we know of this client. */
                   4287:                        packet -> known = 1;
                   4288:                        if (host)
                   4289:                                host_dereference (&host, MDL);
                   4290:                        host_reference (&host, hp, MDL);
                   4291:                        host_dereference (&hp, MDL);
                   4292:                        mockup_lease (&fixed_lease, packet, share, host);
                   4293: #if defined (DEBUG_FIND_LEASE)
                   4294:                        if (fixed_lease) {
                   4295:                                log_info ("Found host for link address: %s.",
                   4296:                                      piaddr (fixed_lease -> ip_addr));
                   4297:                        }
                   4298: #endif
                   4299:                }
                   4300:        }
                   4301:
                   4302:        /* Finally, if we haven't found anything yet try again with the
                   4303:         * host-identifier option ... */
                   4304:        if (!fixed_lease && !host) {
                   4305:                if (find_hosts_by_option(&hp, packet,
                   4306:                                         packet->options, MDL) == 1) {
                   4307:                        packet->known = 1;
                   4308:                        if (host)
                   4309:                                host_dereference(&host, MDL);
                   4310:                        host_reference(&host, hp, MDL);
                   4311:                        host_dereference(&hp, MDL);
                   4312:                        mockup_lease (&fixed_lease, packet, share, host);
                   4313: #if defined (DEBUG_FIND_LEASE)
                   4314:                        if (fixed_lease) {
                   4315:                                log_info ("Found host via host-identifier");
                   4316:                        }
                   4317: #endif
                   4318:                }
                   4319:        }
                   4320:
                   4321:        /* If fixed_lease is present but does not match the requested
                   4322:           IP address, and this is a DHCPREQUEST, then we can't return
                   4323:           any other lease, so we might as well return now. */
                   4324:        if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
                   4325:            (fixed_lease -> ip_addr.len != cip.len ||
                   4326:             memcmp (fixed_lease -> ip_addr.iabuf,
                   4327:                     cip.iabuf, cip.len))) {
                   4328:                if (ours)
                   4329:                        *ours = 1;
                   4330:                strcpy (dhcp_message, "requested address is incorrect");
                   4331: #if defined (DEBUG_FIND_LEASE)
                   4332:                log_info ("Client's fixed-address %s doesn't match %s%s",
                   4333:                          piaddr (fixed_lease -> ip_addr), "request ",
                   4334:                          print_dotted_quads (cip.len, cip.iabuf));
                   4335: #endif
                   4336:                goto out;
                   4337:        }
                   4338:
                   4339:        /*
                   4340:         * If we found leases matching the client identifier, loop through
                   4341:         * the n_uid pointer looking for one that's actually valid.   We
                   4342:         * can't do this until we get here because we depend on
                   4343:         * packet -> known, which may be set by either the uid host
                   4344:         * lookup or the haddr host lookup.
                   4345:         *
                   4346:         * Note that the n_uid lease chain is sorted in order of
                   4347:         * preference, so the first one is the best one.
                   4348:         */
                   4349:        while (uid_lease) {
                   4350:                isc_boolean_t do_release = !packet->raw->ciaddr.s_addr;
                   4351: #if defined (DEBUG_FIND_LEASE)
                   4352:                log_info ("trying next lease matching client id: %s",
                   4353:                          piaddr (uid_lease -> ip_addr));
                   4354: #endif
                   4355:
                   4356: #if defined (FAILOVER_PROTOCOL)
                   4357:                /*
                   4358:                 * When we lookup a lease by uid, we know the client identifier
                   4359:                 * matches the lease's record.  If it is active, or was last
                   4360:                 * active with the same client, we can trivially extend it.
                   4361:                 * If is not or was not active, we can allocate it to this
                   4362:                 * client if it matches the usual free/backup criteria (which
                   4363:                 * is contained in lease_mine_to_reallocate()).
                   4364:                 */
                   4365:                if (uid_lease->binding_state != FTS_ACTIVE &&
                   4366:                    uid_lease->rewind_binding_state != FTS_ACTIVE &&
                   4367:                    !lease_mine_to_reallocate(uid_lease)) {
                   4368: #if defined (DEBUG_FIND_LEASE)
                   4369:                        log_info("not active or not mine to allocate: %s",
                   4370:                                 piaddr(uid_lease->ip_addr));
                   4371: #endif
                   4372:                        goto n_uid;
                   4373:                }
                   4374: #endif
                   4375:
                   4376:                if (uid_lease -> subnet -> shared_network != share) {
                   4377: #if defined (DEBUG_FIND_LEASE)
                   4378:                        log_info ("wrong network segment: %s",
                   4379:                                  piaddr (uid_lease -> ip_addr));
                   4380: #endif
                   4381:                        /* Allow multiple leases using the same UID
                   4382:                           on different subnetworks. */
                   4383:                        do_release = ISC_FALSE;
                   4384:                        goto n_uid;
                   4385:                }
                   4386:
                   4387:                if ((uid_lease -> pool -> prohibit_list &&
                   4388:                     permitted (packet, uid_lease -> pool -> prohibit_list)) ||
                   4389:                    (uid_lease -> pool -> permit_list &&
                   4390:                     !permitted (packet, uid_lease -> pool -> permit_list))) {
                   4391: #if defined (DEBUG_FIND_LEASE)
                   4392:                        log_info ("not permitted: %s",
                   4393:                                  piaddr (uid_lease -> ip_addr));
                   4394: #endif
                   4395:                       n_uid:
                   4396:                        if (uid_lease -> n_uid)
                   4397:                                lease_reference (&next,
                   4398:                                                 uid_lease -> n_uid, MDL);
                   4399:                        if (do_release)
                   4400:                                release_lease (uid_lease, packet);
                   4401:                        lease_dereference (&uid_lease, MDL);
                   4402:                        if (next) {
                   4403:                                lease_reference (&uid_lease, next, MDL);
                   4404:                                lease_dereference (&next, MDL);
                   4405:                        }
                   4406:                        continue;
                   4407:                }
                   4408:                break;
                   4409:        }
                   4410: #if defined (DEBUG_FIND_LEASE)
                   4411:        if (uid_lease)
                   4412:                log_info ("Found lease for client id: %s.",
                   4413:                      piaddr (uid_lease -> ip_addr));
                   4414: #endif
                   4415:
                   4416:        /* Find a lease whose hardware address matches, whose client
                   4417:         * identifier matches (or equally doesn't have one), that's
                   4418:         * permitted, and that's on the correct subnet.
                   4419:         *
                   4420:         * Note that the n_hw chain is sorted in order of preference, so
                   4421:         * the first one found is the best one.
                   4422:         */
                   4423:        h.hlen = packet -> raw -> hlen + 1;
                   4424:        h.hbuf [0] = packet -> raw -> htype;
                   4425:        memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
                   4426:        find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
                   4427:        while (hw_lease) {
                   4428: #if defined (DEBUG_FIND_LEASE)
                   4429:                log_info ("trying next lease matching hw addr: %s",
                   4430:                          piaddr (hw_lease -> ip_addr));
                   4431: #endif
                   4432: #if defined (FAILOVER_PROTOCOL)
                   4433:                /*
                   4434:                 * When we lookup a lease by chaddr, we know the MAC address
                   4435:                 * matches the lease record (we will check if the lease has a
                   4436:                 * client-id the client does not next).  If the lease is
                   4437:                 * currently active or was last active with this client, we can
                   4438:                 * trivially extend it.  Otherwise, there are a set of rules
                   4439:                 * that govern if we can reallocate this lease to any client
                   4440:                 * ("lease_mine_to_reallocate()") including this one.
                   4441:                 */
                   4442:                if (hw_lease->binding_state != FTS_ACTIVE &&
                   4443:                    hw_lease->rewind_binding_state != FTS_ACTIVE &&
                   4444:                    !lease_mine_to_reallocate(hw_lease)) {
                   4445: #if defined (DEBUG_FIND_LEASE)
                   4446:                        log_info("not active or not mine to allocate: %s",
                   4447:                                 piaddr(hw_lease->ip_addr));
                   4448: #endif
                   4449:                        goto n_hw;
                   4450:                }
                   4451: #endif
                   4452:
                   4453:                /*
                   4454:                 * This conditional skips "potentially active" leases (leases
                   4455:                 * we think are expired may be extended by the peer, etc) that
                   4456:                 * may be assigned to a differently /client-identified/ client
                   4457:                 * with the same MAC address.
                   4458:                 */
                   4459:                if (hw_lease -> binding_state != FTS_FREE &&
                   4460:                    hw_lease -> binding_state != FTS_BACKUP &&
                   4461:                    hw_lease -> uid &&
                   4462:                    (!have_client_identifier ||
                   4463:                     hw_lease -> uid_len != client_identifier.len ||
                   4464:                     memcmp (hw_lease -> uid, client_identifier.data,
                   4465:                             hw_lease -> uid_len))) {
                   4466: #if defined (DEBUG_FIND_LEASE)
                   4467:                        log_info ("wrong client identifier: %s",
                   4468:                                  piaddr (hw_lease -> ip_addr));
                   4469: #endif
                   4470:                        goto n_hw;
                   4471:                }
                   4472:                if (hw_lease -> subnet -> shared_network != share) {
                   4473: #if defined (DEBUG_FIND_LEASE)
                   4474:                        log_info ("wrong network segment: %s",
                   4475:                                  piaddr (hw_lease -> ip_addr));
                   4476: #endif
                   4477:                        goto n_hw;
                   4478:                }
                   4479:                if ((hw_lease -> pool -> prohibit_list &&
                   4480:                      permitted (packet, hw_lease -> pool -> prohibit_list)) ||
                   4481:                    (hw_lease -> pool -> permit_list &&
                   4482:                     !permitted (packet, hw_lease -> pool -> permit_list))) {
                   4483: #if defined (DEBUG_FIND_LEASE)
                   4484:                        log_info ("not permitted: %s",
                   4485:                                  piaddr (hw_lease -> ip_addr));
                   4486: #endif
                   4487:                        if (!packet -> raw -> ciaddr.s_addr)
                   4488:                                release_lease (hw_lease, packet);
                   4489:                       n_hw:
                   4490:                        if (hw_lease -> n_hw)
                   4491:                                lease_reference (&next, hw_lease -> n_hw, MDL);
                   4492:                        lease_dereference (&hw_lease, MDL);
                   4493:                        if (next) {
                   4494:                                lease_reference (&hw_lease, next, MDL);
                   4495:                                lease_dereference (&next, MDL);
                   4496:                        }
                   4497:                        continue;
                   4498:                }
                   4499:                break;
                   4500:        }
                   4501: #if defined (DEBUG_FIND_LEASE)
                   4502:        if (hw_lease)
                   4503:                log_info ("Found lease for hardware address: %s.",
                   4504:                      piaddr (hw_lease -> ip_addr));
                   4505: #endif
                   4506:
                   4507:        /* Try to find a lease that's been allocated to the client's
                   4508:           IP address. */
                   4509:        if (ip_lease_in)
                   4510:                lease_reference (&ip_lease, ip_lease_in, MDL);
                   4511:        else if (cip.len)
                   4512:                find_lease_by_ip_addr (&ip_lease, cip, MDL);
                   4513:
                   4514: #if defined (DEBUG_FIND_LEASE)
                   4515:        if (ip_lease)
                   4516:                log_info ("Found lease for requested address: %s.",
                   4517:                      piaddr (ip_lease -> ip_addr));
                   4518: #endif
                   4519:
                   4520:        /* If ip_lease is valid at this point, set ours to one, so that
                   4521:           even if we choose a different lease, we know that the address
                   4522:           the client was requesting was ours, and thus we can NAK it. */
                   4523:        if (ip_lease && ours)
                   4524:                *ours = 1;
                   4525:
                   4526:        /* If the requested IP address isn't on the network the packet
                   4527:           came from, don't use it.  Allow abandoned leases to be matched
                   4528:           here - if the client is requesting it, there's a decent chance
                   4529:           that it's because the lease database got trashed and a client
                   4530:           that thought it had this lease answered an ARP or PING, causing the
                   4531:           lease to be abandoned.   If so, this request probably came from
                   4532:           that client. */
                   4533:        if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
                   4534:                if (ours)
                   4535:                        *ours = 1;
                   4536: #if defined (DEBUG_FIND_LEASE)
                   4537:                log_info ("...but it was on the wrong shared network.");
                   4538: #endif
                   4539:                strcpy (dhcp_message, "requested address on bad subnet");
                   4540:                lease_dereference (&ip_lease, MDL);
                   4541:        }
                   4542:
                   4543:        /*
                   4544:         * If the requested address is in use (or potentially in use) by
                   4545:         * a different client, it can't be granted.
                   4546:         *
                   4547:         * This first conditional only detects if the lease is currently
                   4548:         * identified to a different client (client-id and/or chaddr
                   4549:         * mismatch).  In this case we may not want to give the client the
                   4550:         * lease, if doing so may potentially be an addressing conflict.
                   4551:         */
                   4552:        if (ip_lease &&
                   4553:            (ip_lease -> uid ?
                   4554:             (!have_client_identifier ||
                   4555:              ip_lease -> uid_len != client_identifier.len ||
                   4556:              memcmp (ip_lease -> uid, client_identifier.data,
                   4557:                      ip_lease -> uid_len)) :
                   4558:             (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
                   4559:              ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
                   4560:              memcmp (&ip_lease -> hardware_addr.hbuf [1],
                   4561:                      packet -> raw -> chaddr,
                   4562:                      (unsigned)(ip_lease -> hardware_addr.hlen - 1))))) {
                   4563:                /*
                   4564:                 * A lease is unavailable for allocation to a new client if
                   4565:                 * it is not in the FREE or BACKUP state.  There may be
                   4566:                 * leases that are in the expired state with a rewinding
                   4567:                 * state that is free or backup, but these will be processed
                   4568:                 * into the free or backup states by expiration processes, so
                   4569:                 * checking for them here is superfluous.
                   4570:                 */
                   4571:                if (ip_lease -> binding_state != FTS_FREE &&
                   4572:                    ip_lease -> binding_state != FTS_BACKUP) {
                   4573: #if defined (DEBUG_FIND_LEASE)
                   4574:                        log_info ("rejecting lease for requested address.");
                   4575: #endif
                   4576:                        /* If we're rejecting it because the peer has
                   4577:                           it, don't set "ours", because we shouldn't NAK. */
                   4578:                        if (ours && ip_lease -> binding_state != FTS_ACTIVE)
                   4579:                                *ours = 0;
                   4580:                        lease_dereference (&ip_lease, MDL);
                   4581:                }
                   4582:        }
                   4583:
                   4584:        /*
                   4585:         * If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
                   4586:         * is/was not active, and is not ours to reallocate, forget about it.
                   4587:         */
                   4588:        if (ip_lease && (uid_lease || hw_lease) &&
                   4589:            ip_lease->binding_state != FTS_ACTIVE &&
                   4590:            ip_lease->rewind_binding_state != FTS_ACTIVE &&
                   4591: #if defined(FAILOVER_PROTOCOL)
                   4592:            !lease_mine_to_reallocate(ip_lease) &&
                   4593: #endif
                   4594:            packet->packet_type == DHCPDISCOVER) {
                   4595: #if defined (DEBUG_FIND_LEASE)
                   4596:                log_info("ip lease not active or not ours to offer.");
                   4597: #endif
                   4598:                lease_dereference(&ip_lease, MDL);
                   4599:        }
                   4600:
                   4601:        /* If for some reason the client has more than one lease
                   4602:           on the subnet that matches its uid, pick the one that
                   4603:           it asked for and (if we can) free the other. */
                   4604:        if (ip_lease && ip_lease->binding_state == FTS_ACTIVE &&
                   4605:            ip_lease->uid && ip_lease != uid_lease) {
                   4606:                if (have_client_identifier &&
                   4607:                    (ip_lease -> uid_len == client_identifier.len) &&
                   4608:                    !memcmp (client_identifier.data,
                   4609:                             ip_lease -> uid, ip_lease -> uid_len)) {
                   4610:                        if (uid_lease) {
                   4611:                            if (uid_lease->binding_state == FTS_ACTIVE) {
                   4612:                                log_error ("client %s has duplicate%s on %s",
                   4613:                                           (print_hw_addr
                   4614:                                            (packet -> raw -> htype,
                   4615:                                             packet -> raw -> hlen,
                   4616:                                             packet -> raw -> chaddr)),
                   4617:                                           " leases",
                   4618:                                           (ip_lease -> subnet ->
                   4619:                                            shared_network -> name));
                   4620:
                   4621:                                /* If the client is REQUESTing the lease,
                   4622:                                   it shouldn't still be using the old
                   4623:                                   one, so we can free it for allocation. */
                   4624:                                if (uid_lease &&
                   4625:                                    uid_lease->binding_state == FTS_ACTIVE &&
                   4626:                                    !packet -> raw -> ciaddr.s_addr &&
                   4627:                                    (share ==
                   4628:                                     uid_lease -> subnet -> shared_network) &&
                   4629:                                    packet -> packet_type == DHCPREQUEST)
                   4630:                                        release_lease (uid_lease, packet);
                   4631:                            }
                   4632:                            lease_dereference (&uid_lease, MDL);
                   4633:                            lease_reference (&uid_lease, ip_lease, MDL);
                   4634:                        }
                   4635:                }
                   4636:
                   4637:                /* If we get to here and fixed_lease is not null, that means
                   4638:                   that there are both a dynamic lease and a fixed-address
                   4639:                   declaration for the same IP address. */
                   4640:                if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
                   4641:                        lease_dereference (&fixed_lease, MDL);
                   4642:                      db_conflict:
                   4643:                        log_error ("Dynamic and static leases present for %s.",
                   4644:                                   piaddr (cip));
                   4645:                        log_error ("Remove host declaration %s or remove %s",
                   4646:                                   (fixed_lease && fixed_lease -> host
                   4647:                                    ? (fixed_lease -> host -> name
                   4648:                                       ? fixed_lease -> host -> name
                   4649:                                       : piaddr (cip))
                   4650:                                    : piaddr (cip)),
                   4651:                                    piaddr (cip));
                   4652:                        log_error ("from the dynamic address pool for %s",
                   4653:                                   ip_lease -> subnet -> shared_network -> name
                   4654:                                  );
                   4655:                        if (fixed_lease)
                   4656:                                lease_dereference (&ip_lease, MDL);
                   4657:                        strcpy (dhcp_message,
                   4658:                                "database conflict - call for help!");
                   4659:                }
                   4660:
                   4661:                if (ip_lease && ip_lease != uid_lease) {
                   4662: #if defined (DEBUG_FIND_LEASE)
                   4663:                        log_info ("requested address not available.");
                   4664: #endif
                   4665:                        lease_dereference (&ip_lease, MDL);
                   4666:                }
                   4667:        }
                   4668:
                   4669:        /* If we get to here with both fixed_lease and ip_lease not
                   4670:           null, then we have a configuration file bug. */
                   4671:        if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
                   4672:                goto db_conflict;
                   4673:
                   4674:        /* Toss extra pointers to the same lease... */
                   4675:        if (hw_lease && hw_lease == uid_lease) {
                   4676: #if defined (DEBUG_FIND_LEASE)
                   4677:                log_info ("hardware lease and uid lease are identical.");
                   4678: #endif
                   4679:                lease_dereference (&hw_lease, MDL);
                   4680:        }
                   4681:        if (ip_lease && ip_lease == hw_lease) {
                   4682:                lease_dereference (&hw_lease, MDL);
                   4683: #if defined (DEBUG_FIND_LEASE)
                   4684:                log_info ("hardware lease and ip lease are identical.");
                   4685: #endif
                   4686:        }
                   4687:        if (ip_lease && ip_lease == uid_lease) {
                   4688:                lease_dereference (&uid_lease, MDL);
                   4689: #if defined (DEBUG_FIND_LEASE)
                   4690:                log_info ("uid lease and ip lease are identical.");
                   4691: #endif
                   4692:        }
                   4693:
                   4694:        /* Make sure the client is permitted to use the requested lease. */
                   4695:        if (ip_lease &&
                   4696:            ((ip_lease -> pool -> prohibit_list &&
                   4697:              permitted (packet, ip_lease -> pool -> prohibit_list)) ||
                   4698:             (ip_lease -> pool -> permit_list &&
                   4699:              !permitted (packet, ip_lease -> pool -> permit_list)))) {
                   4700:                if (!packet->raw->ciaddr.s_addr &&
                   4701:                    (ip_lease->binding_state == FTS_ACTIVE))
                   4702:                        release_lease (ip_lease, packet);
                   4703:
                   4704:                lease_dereference (&ip_lease, MDL);
                   4705:        }
                   4706:
                   4707:        if (uid_lease &&
                   4708:            ((uid_lease -> pool -> prohibit_list &&
                   4709:              permitted (packet, uid_lease -> pool -> prohibit_list)) ||
                   4710:             (uid_lease -> pool -> permit_list &&
                   4711:              !permitted (packet, uid_lease -> pool -> permit_list)))) {
                   4712:                if (!packet -> raw -> ciaddr.s_addr)
                   4713:                        release_lease (uid_lease, packet);
                   4714:                lease_dereference (&uid_lease, MDL);
                   4715:        }
                   4716:
                   4717:        if (hw_lease &&
                   4718:            ((hw_lease -> pool -> prohibit_list &&
                   4719:              permitted (packet, hw_lease -> pool -> prohibit_list)) ||
                   4720:             (hw_lease -> pool -> permit_list &&
                   4721:              !permitted (packet, hw_lease -> pool -> permit_list)))) {
                   4722:                if (!packet -> raw -> ciaddr.s_addr)
                   4723:                        release_lease (hw_lease, packet);
                   4724:                lease_dereference (&hw_lease, MDL);
                   4725:        }
                   4726:
                   4727:        /* If we've already eliminated the lease, it wasn't there to
                   4728:           begin with.   If we have come up with a matching lease,
                   4729:           set the message to bad network in case we have to throw it out. */
                   4730:        if (!ip_lease) {
                   4731:                strcpy (dhcp_message, "requested address not available");
                   4732:        }
                   4733:
                   4734:        /* If this is a DHCPREQUEST, make sure the lease we're going to return
                   4735:           matches the requested IP address.   If it doesn't, don't return a
                   4736:           lease at all. */
                   4737:        if (packet -> packet_type == DHCPREQUEST &&
                   4738:            !ip_lease && !fixed_lease) {
                   4739: #if defined (DEBUG_FIND_LEASE)
                   4740:                log_info ("no applicable lease found for DHCPREQUEST.");
                   4741: #endif
                   4742:                goto out;
                   4743:        }
                   4744:
                   4745:        /* At this point, if fixed_lease is nonzero, we can assign it to
                   4746:           this client. */
                   4747:        if (fixed_lease) {
                   4748:                lease_reference (&lease, fixed_lease, MDL);
                   4749:                lease_dereference (&fixed_lease, MDL);
                   4750: #if defined (DEBUG_FIND_LEASE)
                   4751:                log_info ("choosing fixed address.");
                   4752: #endif
                   4753:        }
                   4754:
                   4755:        /* If we got a lease that matched the ip address and don't have
                   4756:           a better offer, use that; otherwise, release it. */
                   4757:        if (ip_lease) {
                   4758:                if (lease) {
                   4759:                        if (!packet -> raw -> ciaddr.s_addr)
                   4760:                                release_lease (ip_lease, packet);
                   4761: #if defined (DEBUG_FIND_LEASE)
                   4762:                        log_info ("not choosing requested address (!).");
                   4763: #endif
                   4764:                        lease_dereference (&ip_lease, MDL);
                   4765:                } else {
                   4766: #if defined (DEBUG_FIND_LEASE)
                   4767:                        log_info ("choosing lease on requested address.");
                   4768: #endif
                   4769:                        lease_reference (&lease, ip_lease, MDL);
                   4770:                        if (lease -> host)
                   4771:                                host_dereference (&lease -> host, MDL);
                   4772:                }
                   4773:        }
                   4774:
                   4775:        /* If we got a lease that matched the client identifier, we may want
                   4776:           to use it, but if we already have a lease we like, we must free
                   4777:           the lease that matched the client identifier. */
                   4778:        if (uid_lease) {
                   4779:                if (lease) {
                   4780:                        log_error("uid lease %s for client %s is duplicate "
                   4781:                                  "on %s",
                   4782:                                  piaddr(uid_lease->ip_addr),
                   4783:                                  print_hw_addr(packet->raw->htype,
                   4784:                                                packet->raw->hlen,
                   4785:                                                packet->raw->chaddr),
                   4786:                                  uid_lease->subnet->shared_network->name);
                   4787:
                   4788:                        if (!packet -> raw -> ciaddr.s_addr &&
                   4789:                            packet -> packet_type == DHCPREQUEST &&
                   4790:                            uid_lease -> binding_state == FTS_ACTIVE)
                   4791:                                release_lease(uid_lease, packet);
                   4792: #if defined (DEBUG_FIND_LEASE)
                   4793:                        log_info ("not choosing uid lease.");
                   4794: #endif
                   4795:                } else {
                   4796:                        lease_reference (&lease, uid_lease, MDL);
                   4797:                        if (lease -> host)
                   4798:                                host_dereference (&lease -> host, MDL);
                   4799: #if defined (DEBUG_FIND_LEASE)
                   4800:                        log_info ("choosing uid lease.");
                   4801: #endif
                   4802:                }
                   4803:                lease_dereference (&uid_lease, MDL);
                   4804:        }
                   4805:
                   4806:        /* The lease that matched the hardware address is treated likewise. */
                   4807:        if (hw_lease) {
                   4808:                if (lease) {
                   4809: #if defined (DEBUG_FIND_LEASE)
                   4810:                        log_info ("not choosing hardware lease.");
                   4811: #endif
                   4812:                } else {
                   4813:                        /* We're a little lax here - if the client didn't
                   4814:                           send a client identifier and it's a bootp client,
                   4815:                           but the lease has a client identifier, we still
                   4816:                           let the client have a lease. */
                   4817:                        if (!hw_lease -> uid_len ||
                   4818:                            (have_client_identifier
                   4819:                             ? (hw_lease -> uid_len ==
                   4820:                                client_identifier.len &&
                   4821:                                !memcmp (hw_lease -> uid,
                   4822:                                         client_identifier.data,
                   4823:                                         client_identifier.len))
                   4824:                             : packet -> packet_type == 0)) {
                   4825:                                lease_reference (&lease, hw_lease, MDL);
                   4826:                                if (lease -> host)
                   4827:                                        host_dereference (&lease -> host, MDL);
                   4828: #if defined (DEBUG_FIND_LEASE)
                   4829:                                log_info ("choosing hardware lease.");
                   4830: #endif
                   4831:                        } else {
                   4832: #if defined (DEBUG_FIND_LEASE)
                   4833:                                log_info ("not choosing hardware lease: %s.",
                   4834:                                          "uid mismatch");
                   4835: #endif
                   4836:                        }
                   4837:                }
                   4838:                lease_dereference (&hw_lease, MDL);
                   4839:        }
                   4840:
                   4841:        /*
                   4842:         * If we found a host_decl but no matching address, try to
                   4843:         * find a host_decl that has no address, and if there is one,
                   4844:         * hang it off the lease so that we can use the supplied
                   4845:         * options.
                   4846:         */
                   4847:        if (lease && host && !lease->host) {
                   4848:                struct host_decl *p = NULL;
                   4849:                struct host_decl *n = NULL;
                   4850:
                   4851:                host_reference(&p, host, MDL);
                   4852:                while (p != NULL) {
                   4853:                        if (!p->fixed_addr) {
                   4854:                                /*
                   4855:                                 * If the lease is currently active, then it
                   4856:                                 * must be allocated to the present client.
                   4857:                                 * We store a reference to the host record on
                   4858:                                 * the lease to save a lookup later (in
                   4859:                                 * ack_lease()).  We mustn't refer to the host
                   4860:                                 * record on non-active leases because the
                   4861:                                 * client may be denied later.
                   4862:                                 *
                   4863:                                 * XXX: Not having this reference (such as in
                   4864:                                 * DHCPDISCOVER/INIT) means ack_lease will have
                   4865:                                 * to perform this lookup a second time.  This
                   4866:                                 * hopefully isn't a problem as DHCPREQUEST is
                   4867:                                 * more common than DHCPDISCOVER.
                   4868:                                 */
                   4869:                                if (lease->binding_state == FTS_ACTIVE)
                   4870:                                        host_reference(&lease->host, p, MDL);
                   4871:
                   4872:                                host_dereference(&p, MDL);
                   4873:                                break;
                   4874:                        }
                   4875:                        if (p->n_ipaddr != NULL)
                   4876:                                host_reference(&n, p->n_ipaddr, MDL);
                   4877:                        host_dereference(&p, MDL);
                   4878:                        if (n != NULL) {
                   4879:                                host_reference(&p, n, MDL);
                   4880:                                host_dereference(&n, MDL);
                   4881:                        }
                   4882:                }
                   4883:        }
                   4884:
                   4885:        /* If we find an abandoned lease, but it's the one the client
                   4886:           requested, we assume that previous bugginess on the part
                   4887:           of the client, or a server database loss, caused the lease to
                   4888:           be abandoned, so we reclaim it and let the client have it. */
                   4889:        if (lease &&
                   4890:            (lease -> binding_state == FTS_ABANDONED) &&
                   4891:            lease == ip_lease &&
                   4892:            packet -> packet_type == DHCPREQUEST) {
                   4893:                log_error ("Reclaiming REQUESTed abandoned IP address %s.",
                   4894:                      piaddr (lease -> ip_addr));
                   4895:        } else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
                   4896:        /* Otherwise, if it's not the one the client requested, we do not
                   4897:           return it - instead, we claim it's ours, causing a DHCPNAK to be
                   4898:           sent if this lookup is for a DHCPREQUEST, and force the client
                   4899:           to go back through the allocation process. */
                   4900:                if (ours)
                   4901:                        *ours = 1;
                   4902:                lease_dereference (&lease, MDL);
                   4903:        }
                   4904:
                   4905:       out:
                   4906:        if (have_client_identifier)
                   4907:                data_string_forget (&client_identifier, MDL);
                   4908:
                   4909:        if (fixed_lease)
                   4910:                lease_dereference (&fixed_lease, MDL);
                   4911:        if (hw_lease)
                   4912:                lease_dereference (&hw_lease, MDL);
                   4913:        if (uid_lease)
                   4914:                lease_dereference (&uid_lease, MDL);
                   4915:        if (ip_lease)
                   4916:                lease_dereference (&ip_lease, MDL);
                   4917:        if (host)
                   4918:                host_dereference (&host, MDL);
                   4919:
                   4920:        if (lease) {
                   4921: #if defined (DEBUG_FIND_LEASE)
                   4922:                log_info ("Returning lease: %s.",
                   4923:                      piaddr (lease -> ip_addr));
                   4924: #endif
                   4925:                lease_reference (lp, lease, file, line);
                   4926:                lease_dereference (&lease, MDL);
                   4927:                return 1;
                   4928:        }
                   4929: #if defined (DEBUG_FIND_LEASE)
                   4930:        log_info ("Not returning a lease.");
                   4931: #endif
                   4932:        return 0;
                   4933: }
                   4934:
                   4935: /* Search the provided host_decl structure list for an address that's on
                   4936:    the specified shared network.  If one is found, mock up and return a
                   4937:    lease structure for it; otherwise return the null pointer. */
                   4938:
                   4939: int mockup_lease (struct lease **lp, struct packet *packet,
                   4940:                  struct shared_network *share, struct host_decl *hp)
                   4941: {
                   4942:        struct lease *lease = (struct lease *)0;
                   4943:        struct host_decl *rhp = (struct host_decl *)0;
1.1.1.2   christos 4944:
1.1       christos 4945:        if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS)
                   4946:                return 0;
                   4947:        if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) {
                   4948:                lease_dereference (&lease, MDL);
                   4949:                return 0;
                   4950:        }
                   4951:        if (!find_host_for_network (&lease -> subnet,
                   4952:                                    &rhp, &lease -> ip_addr, share)) {
                   4953:                lease_dereference (&lease, MDL);
                   4954:                host_dereference (&rhp, MDL);
                   4955:                return 0;
                   4956:        }
                   4957:        host_reference (&lease -> host, rhp, MDL);
                   4958:        if (rhp -> client_identifier.len > sizeof lease -> uid_buf)
                   4959:                lease -> uid = dmalloc (rhp -> client_identifier.len, MDL);
                   4960:        else
                   4961:                lease -> uid = lease -> uid_buf;
                   4962:        if (!lease -> uid) {
                   4963:                lease_dereference (&lease, MDL);
                   4964:                host_dereference (&rhp, MDL);
                   4965:                return 0;
                   4966:        }
                   4967:        memcpy (lease -> uid, rhp -> client_identifier.data,
                   4968:                rhp -> client_identifier.len);
                   4969:        lease -> uid_len = rhp -> client_identifier.len;
                   4970:        lease -> hardware_addr = rhp -> interface;
                   4971:        lease -> starts = lease -> cltt = lease -> ends = MIN_TIME;
                   4972:        lease -> flags = STATIC_LEASE;
                   4973:        lease -> binding_state = FTS_FREE;
                   4974:
                   4975:        lease_reference (lp, lease, MDL);
                   4976:
                   4977:        lease_dereference (&lease, MDL);
                   4978:        host_dereference (&rhp, MDL);
                   4979:        return 1;
                   4980: }
                   4981:
                   4982: /* Look through all the pools in a list starting with the specified pool
                   4983:    for a free lease.   We try to find a virgin lease if we can.   If we
                   4984:    don't find a virgin lease, we try to find a non-virgin lease that's
                   4985:    free.   If we can't find one of those, we try to reclaim an abandoned
                   4986:    lease.   If all of these possibilities fail to pan out, we don't return
                   4987:    a lease at all. */
                   4988:
                   4989: int allocate_lease (struct lease **lp, struct packet *packet,
                   4990:                    struct pool *pool, int *peer_has_leases)
                   4991: {
                   4992:        struct lease *lease = NULL;
                   4993:        struct lease *candl = NULL;
                   4994:
                   4995:        for (; pool ; pool = pool -> next) {
                   4996:                if ((pool -> prohibit_list &&
                   4997:                     permitted (packet, pool -> prohibit_list)) ||
                   4998:                    (pool -> permit_list &&
                   4999:                     !permitted (packet, pool -> permit_list)))
                   5000:                        continue;
                   5001:
                   5002: #if defined (FAILOVER_PROTOCOL)
                   5003:                /* Peer_has_leases just says that we found at least one
                   5004:                   free lease.  If no free lease is returned, the caller
                   5005:                   can deduce that this means the peer is hogging all the
                   5006:                   free leases, so we can print a better error message. */
                   5007:                /* XXX Do we need code here to ignore PEER_IS_OWNER and
                   5008:                 * XXX just check tstp if we're in, e.g., PARTNER_DOWN?
                   5009:                 * XXX Where do we deal with CONFLICT_DETECTED, et al? */
                   5010:                /* XXX This should be handled by the lease binding "state
                   5011:                 * XXX machine" - that is, when we get here, if a lease
                   5012:                 * XXX could be allocated, it will have the correct
                   5013:                 * XXX binding state so that the following code will
                   5014:                 * XXX result in its being allocated. */
                   5015:                /* Skip to the most expired lease in the pool that is not
                   5016:                 * owned by a failover peer. */
                   5017:                if (pool->failover_peer != NULL) {
                   5018:                        struct lease *peerl = NULL;
                   5019:                        if (pool->failover_peer->i_am == primary) {
                   5020:                                candl = LEASE_GET_FIRST(pool->free);
                   5021:
                   5022:                                /*
                   5023:                                 * In normal operation, we never want to touch
1.1.1.2   christos 5024:                                 * the peer's leases.  In partner-down
1.1       christos 5025:                                 * operation, we need to be able to pick up
                   5026:                                 * the peer's leases after STOS+MCLT.
                   5027:                                 */
                   5028:                                peerl = LEASE_GET_FIRST(pool->backup);
                   5029:                                if (peerl != NULL) {
                   5030:                                        if (((candl == NULL) ||
                   5031:                                             (candl->ends > peerl->ends)) &&
                   5032:                                            lease_mine_to_reallocate(peerl)) {
                   5033:                                                candl = peerl;
                   5034:                                        } else {
                   5035:                                                *peer_has_leases = 1;
                   5036:                                        }
                   5037:                                }
                   5038:                        } else {
                   5039:                                candl = LEASE_GET_FIRST(pool->backup);
                   5040:
                   5041:                                peerl = LEASE_GET_FIRST(pool->free);
                   5042:                                if (peerl != NULL) {
                   5043:                                        if (((candl == NULL) ||
                   5044:                                             (candl->ends > peerl->ends)) &&
                   5045:                                            lease_mine_to_reallocate(peerl)) {
                   5046:                                                candl = peerl;
                   5047:                                        } else {
                   5048:                                                *peer_has_leases = 1;
                   5049:                                        }
                   5050:                                }
                   5051:                        }
                   5052:
                   5053:                        /* Try abandoned leases as a last resort. */
                   5054:                        peerl = LEASE_GET_FIRST(pool->abandoned);
                   5055:                        if ((candl == NULL) && (peerl != NULL) &&
                   5056:                            lease_mine_to_reallocate(peerl))
                   5057:                                candl = peerl;
                   5058:                } else
                   5059: #endif
                   5060:                {
                   5061:                        if (LEASE_NOT_EMPTY(pool->free))
                   5062:                                candl = LEASE_GET_FIRST(pool->free);
                   5063:                        else
                   5064:                                candl = LEASE_GET_FIRST(pool->abandoned);
                   5065:                }
                   5066:
                   5067:                /*
                   5068:                 * XXX: This may not match with documented expectation.
                   5069:                 * It's expected that when we OFFER a lease, we set its
                   5070:                 * ends time forward 2 minutes so that it gets sorted to
                   5071:                 * the end of its free list (avoiding a similar allocation
                   5072:                 * to another client).  It is not expected that we issue a
                   5073:                 * "no free leases" error when the last lease has been
                   5074:                 * offered, but it's not exactly broken either.
                   5075:                 */
                   5076:                if (!candl ||
                   5077:                    (candl->binding_state != FTS_ABANDONED &&
                   5078:                     (candl->ends > cur_time))) {
                   5079:                        continue;
                   5080:                }
                   5081:
                   5082:                if (!lease) {
                   5083:                        lease = candl;
                   5084:                        continue;
                   5085:                }
                   5086:
                   5087:                /*
                   5088:                 * There are tiers of lease state preference, listed here in
                   5089:                 * reverse order (least to most preferential):
                   5090:                 *
                   5091:                 *    ABANDONED
                   5092:                 *    FREE/BACKUP
                   5093:                 *
                   5094:                 * If the selected lease and candidate are both of the same
                   5095:                 * state, select the oldest (longest ago) expiration time
                   5096:                 * between the two.  If the candidate lease is of a higher
                   5097:                 * preferred grade over the selected lease, use it.
                   5098:                 */
                   5099:                if ((lease -> binding_state == FTS_ABANDONED) &&
                   5100:                    ((candl -> binding_state != FTS_ABANDONED) ||
                   5101:                     (candl -> ends < lease -> ends))) {
                   5102:                        lease = candl;
                   5103:                        continue;
                   5104:                } else if (candl -> binding_state == FTS_ABANDONED)
                   5105:                        continue;
                   5106:
                   5107:                if ((lease -> uid_len || lease -> hardware_addr.hlen) &&
                   5108:                    ((!candl -> uid_len && !candl -> hardware_addr.hlen) ||
                   5109:                     (candl -> ends < lease -> ends))) {
                   5110:                        lease = candl;
                   5111:                        continue;
                   5112:                } else if (candl -> uid_len || candl -> hardware_addr.hlen)
                   5113:                        continue;
                   5114:
                   5115:                if (candl -> ends < lease -> ends)
                   5116:                        lease = candl;
                   5117:        }
                   5118:
                   5119:        if (lease != NULL) {
                   5120:                if (lease->binding_state == FTS_ABANDONED)
                   5121:                        log_error("Reclaiming abandoned lease %s.",
                   5122:                                  piaddr(lease->ip_addr));
                   5123:
                   5124:                /*
                   5125:                 * XXX: For reliability, we go ahead and remove the host
                   5126:                 * record and try to move on.  For correctness, if there
                   5127:                 * are any other stale host vectors, we want to find them.
                   5128:                 */
                   5129:                if (lease->host != NULL) {
                   5130:                        log_debug("soft impossible condition (%s:%d): stale "
                   5131:                                  "host \"%s\" found on lease %s", MDL,
                   5132:                                  lease->host->name,
                   5133:                                  piaddr(lease->ip_addr));
                   5134:                        host_dereference(&lease->host, MDL);
                   5135:                }
                   5136:
                   5137:                lease_reference (lp, lease, MDL);
                   5138:                return 1;
                   5139:        }
                   5140:
                   5141:        return 0;
                   5142: }
                   5143:
                   5144: /* Determine whether or not a permit exists on a particular permit list
                   5145:    that matches the specified packet, returning nonzero if so, zero if
                   5146:    not. */
                   5147:
                   5148: int permitted (packet, permit_list)
                   5149:        struct packet *packet;
                   5150:        struct permit *permit_list;
                   5151: {
                   5152:        struct permit *p;
                   5153:        int i;
                   5154:
                   5155:        for (p = permit_list; p; p = p -> next) {
                   5156:                switch (p -> type) {
                   5157:                      case permit_unknown_clients:
                   5158:                        if (!packet -> known)
                   5159:                                return 1;
                   5160:                        break;
                   5161:
                   5162:                      case permit_known_clients:
                   5163:                        if (packet -> known)
                   5164:                                return 1;
                   5165:                        break;
                   5166:
                   5167:                      case permit_authenticated_clients:
                   5168:                        if (packet -> authenticated)
                   5169:                                return 1;
                   5170:                        break;
                   5171:
                   5172:                      case permit_unauthenticated_clients:
                   5173:                        if (!packet -> authenticated)
                   5174:                                return 1;
                   5175:                        break;
                   5176:
                   5177:                      case permit_all_clients:
                   5178:                        return 1;
                   5179:
                   5180:                      case permit_dynamic_bootp_clients:
                   5181:                        if (!packet -> options_valid ||
                   5182:                            !packet -> packet_type)
                   5183:                                return 1;
                   5184:                        break;
1.1.1.2   christos 5185:
1.1       christos 5186:                      case permit_class:
                   5187:                        for (i = 0; i < packet -> class_count; i++) {
                   5188:                                if (p -> class == packet -> classes [i])
                   5189:                                        return 1;
                   5190:                                if (packet -> classes [i] &&
                   5191:                                    packet -> classes [i] -> superclass &&
                   5192:                                    (packet -> classes [i] -> superclass ==
                   5193:                                     p -> class))
                   5194:                                        return 1;
                   5195:                        }
                   5196:                        break;
                   5197:
                   5198:                      case permit_after:
                   5199:                        if (cur_time > p->after)
                   5200:                                return 1;
                   5201:                        break;
                   5202:                }
                   5203:        }
                   5204:        return 0;
                   5205: }
                   5206:
                   5207: #if defined(DHCPv6) && defined(DHCP4o6)
                   5208: static int locate_network6 (packet)
                   5209:        struct packet *packet;
                   5210: {
                   5211:        const struct packet *chk_packet;
                   5212:        const struct in6_addr *link_addr, *first_link_addr;
                   5213:        struct iaddr ia;
                   5214:        struct data_string data;
                   5215:        struct subnet *subnet = NULL;
                   5216:        struct option_cache *oc;
                   5217:
                   5218:        /* from locate_network() */
                   5219:
                   5220:        /* See if there's a Relay Agent Link Selection Option, or a
                   5221:         * Subnet Selection Option.  The Link-Select and Subnet-Select
                   5222:         * are formatted and used precisely the same, but we must prefer
                   5223:         * the link-select over the subnet-select.
                   5224:         * BTW in DHCPv4 over DHCPv6 no cross version relay was specified
                   5225:         * so it is unlikely to see a link-select.
                   5226:         */
                   5227:        if ((oc = lookup_option(&agent_universe, packet->options,
                   5228:                                RAI_LINK_SELECT)) == NULL)
                   5229:                oc = lookup_option(&dhcp_universe, packet->options,
                   5230:                                   DHO_SUBNET_SELECTION);
                   5231:
                   5232:        /* If there's an option indicating link connection or subnet
                   5233:         * selection, and it's valid, use it to figure out the subnet.
                   5234:         * If it's not valid, fail.
                   5235:         */
                   5236:        if (oc) {
                   5237:                memset(&data, 0, sizeof data);
                   5238:                if (!evaluate_option_cache(&data, packet, NULL, NULL,
                   5239:                                           packet->options, NULL,
                   5240:                                           &global_scope, oc, MDL)) {
                   5241:                        return (0);
                   5242:                }
                   5243:                if (data.len == 0) {
                   5244:                        return (0);
                   5245:                }
                   5246:                if (data.len != 4) {
                   5247:                        data_string_forget(&data, MDL);
                   5248:                        return (0);
                   5249:                }
                   5250:                ia.len = 4;
                   5251:                memcpy(ia.iabuf, data.data, 4);
                   5252:                data_string_forget(&data, MDL);
                   5253:
                   5254:                if (find_subnet(&subnet, ia, MDL)) {
                   5255:                        shared_network_reference(&packet->shared_network,
                   5256:                                                 subnet->shared_network, MDL);
                   5257:                        subnet_dereference(&subnet, MDL);
                   5258:                        return (1);
                   5259:                }
                   5260:                return (0);
                   5261:        }
                   5262:
                   5263:        /* See if there is a giaddr (still unlikely), if there is one
                   5264:         * use it to figure out the subnet.  If it's not valid, fail.
                   5265:         */
                   5266:        if (packet->raw->giaddr.s_addr) {
                   5267:                ia.len = 4;
                   5268:                memcpy(ia.iabuf, &packet->raw->giaddr, 4);
                   5269:
                   5270:                if (find_subnet(&subnet, ia, MDL)) {
                   5271:                        shared_network_reference(&packet->shared_network,
                   5272:                                                 subnet->shared_network, MDL);
                   5273:                        subnet_dereference(&subnet, MDL);
                   5274:                        return (1);
                   5275:                }
                   5276:                return (0);
                   5277:        }
                   5278:
                   5279:        /* from shared_network_from_packet6() */
                   5280:
                   5281:        /* First, find the link address where the packet from the client
                   5282:         * first appeared (if this packet was relayed).
                   5283:         */
                   5284:        first_link_addr = NULL;
                   5285:        chk_packet = packet->dhcpv6_container_packet;
                   5286:        while (chk_packet != NULL) {
                   5287:                link_addr = &chk_packet->dhcpv6_link_address;
                   5288:                if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
                   5289:                    !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
                   5290:                        first_link_addr = link_addr;
                   5291:                        break;
                   5292:                }
                   5293:                chk_packet = chk_packet->dhcpv6_container_packet;
                   5294:        }
                   5295:
                   5296:        /* If there is a relayed link address, find the subnet associated
                   5297:         * with that, and use that to get the appropriate shared_network.
                   5298:         */
                   5299:        if (first_link_addr != NULL) {
                   5300:                ia.len = sizeof(*first_link_addr);
                   5301:                memcpy(ia.iabuf, first_link_addr, sizeof(*first_link_addr));
                   5302:                if (find_subnet (&subnet, ia, MDL)) {
                   5303:                        shared_network_reference(&packet->shared_network,
                   5304:                                                 subnet->shared_network, MDL);
                   5305:                        subnet_dereference(&subnet, MDL);
                   5306:                        return (1);
                   5307:                }
                   5308:                return (0);
                   5309:        }
                   5310:
                   5311:        /* If there is no link address, we will use the interface
                   5312:         * that this packet came in on to pick the shared_network.
                   5313:         */
                   5314:        if (packet->interface != NULL) {
                   5315:                if (packet->interface->shared_network == NULL)
                   5316:                        return (0);
                   5317:                shared_network_reference(&packet->shared_network,
                   5318:                                         packet->interface->shared_network,
                   5319:                                         MDL);
                   5320:                return (1);
                   5321:        }
                   5322:
                   5323:        /* We shouldn't be able to get here but if there is no link
                   5324:         * address and no interface we don't know where to get the
                   5325:         * shared_network from, log an error and return an error.
                   5326:         */
                   5327:        log_error("No interface and no link address "
                   5328:                  "can't determine DHCP4o6 shared network");
                   5329:        return (0);
                   5330: }
                   5331: #endif
                   5332:
                   5333: int locate_network (packet)
                   5334:        struct packet *packet;
                   5335: {
                   5336:        struct iaddr ia;
                   5337:        struct data_string data;
                   5338:        struct subnet *subnet = (struct subnet *)0;
                   5339:        struct option_cache *oc;
                   5340:
                   5341: #if defined(DHCPv6) && defined(DHCP4o6)
                   5342:        if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
                   5343:                return (locate_network6 (packet));
                   5344:        }
                   5345: #endif
                   5346:
                   5347:        /* See if there's a Relay Agent Link Selection Option, or a
                   5348:         * Subnet Selection Option.  The Link-Select and Subnet-Select
                   5349:         * are formatted and used precisely the same, but we must prefer
                   5350:         * the link-select over the subnet-select.
                   5351:         */
                   5352:        if ((oc = lookup_option(&agent_universe, packet->options,
                   5353:                                RAI_LINK_SELECT)) == NULL)
                   5354:                oc = lookup_option(&dhcp_universe, packet->options,
                   5355:                                   DHO_SUBNET_SELECTION);
                   5356:
                   5357:        /* If there's no SSO and no giaddr, then use the shared_network
                   5358:           from the interface, if there is one.   If not, fail. */
                   5359:        if (!oc && !packet -> raw -> giaddr.s_addr) {
                   5360:                if (packet -> interface -> shared_network) {
                   5361:                        shared_network_reference
                   5362:                                (&packet -> shared_network,
                   5363:                                 packet -> interface -> shared_network, MDL);
                   5364:                        return 1;
                   5365:                }
                   5366:                return 0;
                   5367:        }
                   5368:
                   5369:        /* If there's an option indicating link connection, and it's valid,
                   5370:         * use it to figure out the subnet.  If it's not valid, fail.
                   5371:         */
                   5372:        if (oc) {
                   5373:                memset (&data, 0, sizeof data);
                   5374:                if (!evaluate_option_cache (&data, packet, (struct lease *)0,
                   5375:                                            (struct client_state *)0,
                   5376:                                            packet -> options,
                   5377:                                            (struct option_state *)0,
                   5378:                                            &global_scope, oc, MDL)) {
                   5379:                        return 0;
                   5380:                }
1.1.1.2   christos 5381:
1.1       christos 5382:                if (data.len != 4) {
                   5383:                        data_string_forget (&data, MDL);
                   5384:                        return 0;
                   5385:                }
1.1.1.2   christos 5386:
1.1       christos 5387:                ia.len = 4;
                   5388:                memcpy (ia.iabuf, data.data, 4);
                   5389:                data_string_forget (&data, MDL);
                   5390:        } else {
                   5391:                ia.len = 4;
                   5392:                memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
                   5393:        }
                   5394:
                   5395:        /* If we know the subnet on which the IP address lives, use it. */
                   5396:        if (find_subnet (&subnet, ia, MDL)) {
                   5397:                shared_network_reference (&packet -> shared_network,
                   5398:                                          subnet -> shared_network, MDL);
                   5399:                subnet_dereference (&subnet, MDL);
                   5400:                return 1;
                   5401:        }
                   5402:
                   5403:        /* Otherwise, fail. */
                   5404:        return 0;
                   5405: }
                   5406:
                   5407: /*
                   5408:  * Try to figure out the source address to send packets from.
                   5409:  *
                   5410:  * from is the address structure we use to return any address
                   5411:  * we find.
                   5412:  *
                   5413:  * options is the option cache to search.  This may include
                   5414:  * options from the incoming packet and configuration information.
                   5415:  *
                   5416:  * out_options is the outgoing option cache.  This cache
                   5417:  * may be the same as options.  If out_options isn't NULL
                   5418:  * we may save the server address option into it.  We do so
                   5419:  * if out_options is different than options or if the option
                   5420:  * wasn't in options and we needed to find the address elsewhere.
                   5421:  *
                   5422:  * packet is the state structure for the incoming packet
                   5423:  *
                   5424:  * When finding the address we first check to see if it is
                   5425:  * in the options list.  If it isn't we use the first address
                   5426:  * from the interface.
                   5427:  *
                   5428:  * While this is slightly more complicated than I'd like it allows
                   5429:  * us to use the same code in several different places.  ack,
                   5430:  * inform and lease query use it to find the address and fill
                   5431:  * in the options if we get the address from the interface.
                   5432:  * nack uses it to find the address and copy it to the outgoing
                   5433:  * cache.  dhcprequest uses it to find the address for comparison
                   5434:  * and doesn't need to add it to an outgoing list.
                   5435:  */
                   5436:
                   5437: void
                   5438: get_server_source_address(struct in_addr *from,
                   5439:                          struct option_state *options,
                   5440:                          struct option_state *out_options,
                   5441:                          struct packet *packet) {
                   5442:        unsigned option_num;
                   5443:        struct option_cache *oc = NULL;
                   5444:        struct data_string d;
                   5445:        struct in_addr *a = NULL;
                   5446:        isc_boolean_t found = ISC_FALSE;
                   5447:        int allocate = 0;
                   5448:
                   5449:        memset(&d, 0, sizeof(d));
                   5450:        memset(from, 0, sizeof(*from));
                   5451:
                   5452:                option_num = DHO_DHCP_SERVER_IDENTIFIER;
                   5453:                oc = lookup_option(&dhcp_universe, options, option_num);
                   5454:                if (oc != NULL)  {
1.1.1.2   christos 5455:                if (evaluate_option_cache(&d, packet, NULL, NULL,
                   5456:                                          packet->options, options,
1.1       christos 5457:                                          &global_scope, oc, MDL)) {
                   5458:                        if (d.len == sizeof(*from)) {
                   5459:                                found = ISC_TRUE;
                   5460:                                memcpy(from, d.data, sizeof(*from));
                   5461:
                   5462:                                /*
                   5463:                                 * Arrange to save a copy of the data
                   5464:                                 * to the outgoing list.
                   5465:                                 */
                   5466:                                if ((out_options != NULL) &&
                   5467:                                    (options != out_options)) {
                   5468:                                        a = from;
                   5469:                                        allocate = 1;
                   5470:                                }
                   5471:                        }
                   5472:                        data_string_forget(&d, MDL);
                   5473:                }
                   5474:                oc = NULL;
                   5475:        }
                   5476:
                   5477:        if ((found == ISC_FALSE) &&
                   5478:            (packet->interface->address_count > 0)) {
                   5479:                *from = packet->interface->addresses[0];
                   5480:
                   5481:                if (out_options != NULL) {
                   5482:                        a = &packet->interface->addresses[0];
                   5483:                }
                   5484:        }
                   5485:
                   5486:        if ((a != NULL) &&
                   5487:            (option_cache_allocate(&oc, MDL))) {
                   5488:                if (make_const_data(&oc->expression,
                   5489:                                    (unsigned char *)a, sizeof(*a),
                   5490:                                    0, allocate, MDL)) {
1.1.1.2   christos 5491:                        option_code_hash_lookup(&oc->option,
1.1       christos 5492:                                                dhcp_universe.code_hash,
                   5493:                                                &option_num, 0, MDL);
                   5494:                        save_option(&dhcp_universe, out_options, oc);
                   5495:                }
                   5496:                option_cache_dereference(&oc, MDL);
                   5497:        }
                   5498:
                   5499:        return;
                   5500: }
                   5501:
                   5502: /*!
                   5503:  * \brief Builds option set from statements at the global and network scope
                   5504:  *
                   5505:  * Set up an option state list based on the global and network scopes.
                   5506:  * These are primarily used by NAK logic to locate dhcp-server-id and
                   5507:  * echo-client-id.
                   5508:  *
                   5509:  * We don't go through all possible options - in particualr we skip the hosts
                   5510:  * and we don't include the lease to avoid making changes to it. This means
                   5511:  * that using these, we won't get the correct server id if the admin puts them
                   5512:  * on hosts or builds the server id with information from the lease.
                   5513:  *
                   5514:  * As this is a fallback function (used to handle NAKs or sort out server id
                   5515:  * mismatch in failover) and requires configuration by the admin, it should be
                   5516:  * okay.
                   5517:  *
                   5518:  * \param network_options option_state to which options will be added. If it
                   5519:  * refers to NULL, it will be allocated.  Caller is responsible to delete it.
                   5520:  * \param packet inbound packet
                   5521:  * \param network_group scope group to use if packet->shared_network is null.
                   5522:  */
                   5523: void
                   5524: eval_network_statements(struct option_state **network_options,
                   5525:                        struct packet *packet,
                   5526:                        struct group *network_group) {
                   5527:
                   5528:        if (*network_options == NULL) {
                   5529:                option_state_allocate (network_options, MDL);
                   5530:        }
                   5531:
                   5532:        /* Use the packet's shared_network if it has one.  If not use
                   5533:          * network_group and if it is null then use global scope. */
                   5534:        if (packet->shared_network != NULL) {
                   5535:                /*
                   5536:                 * If we have a subnet and group start with that else start
                   5537:                 * with the shared network group.  The first will recurse and
                   5538:                 * include the second.
                   5539:                 */
                   5540:                if ((packet->shared_network->subnets != NULL) &&
                   5541:                    (packet->shared_network->subnets->group != NULL)) {
                   5542:                        execute_statements_in_scope(NULL, packet, NULL, NULL,
                   5543:                                        packet->options, *network_options,
                   5544:                                        &global_scope,
                   5545:                                        packet->shared_network->subnets->group,
                   5546:                                        NULL, NULL);
                   5547:                } else {
                   5548:                        execute_statements_in_scope(NULL, packet, NULL, NULL,
                   5549:                                        packet->options, *network_options,
                   5550:                                        &global_scope,
                   5551:                                        packet->shared_network->group,
                   5552:                                        NULL, NULL);
                   5553:                }
                   5554:
                   5555:                /* do the pool if there is one */
                   5556:                if (packet->shared_network->pools != NULL) {
                   5557:                        execute_statements_in_scope(NULL, packet, NULL, NULL,
                   5558:                                        packet->options, *network_options,
                   5559:                                        &global_scope,
                   5560:                                        packet->shared_network->pools->group,
                   5561:                                        packet->shared_network->group,
                   5562:                                        NULL);
                   5563:                }
                   5564:        } else if (network_group != NULL) {
                   5565:                 execute_statements_in_scope(NULL, packet, NULL, NULL,
                   5566:                                             packet->options, *network_options,
                   5567:                                             &global_scope, network_group,
                   5568:                                             NULL, NULL);
                   5569:        } else {
                   5570:                 execute_statements_in_scope(NULL, packet, NULL, NULL,
                   5571:                                             packet->options, *network_options,
                   5572:                                             &global_scope, root_group,
                   5573:                                             NULL, NULL);
                   5574:     }
                   5575: }
                   5576:
                   5577: /*
                   5578:  * Look for the lowest numbered site code number and
                   5579:  * apply a log warning if it is less than 224.  Do not
                   5580:  * permit site codes less than 128 (old code never did).
                   5581:  *
                   5582:  * Note that we could search option codes 224 down to 128
                   5583:  * on the hash table, but the table is (probably) smaller
                   5584:  * than that if it was declared as a standalone table with
                   5585:  * defaults.  So we traverse the option code hash.
                   5586:  */
                   5587: static int
                   5588: find_min_site_code(struct universe *u)
                   5589: {
                   5590:        if (u->site_code_min)
                   5591:                return u->site_code_min;
                   5592:
                   5593:        /*
                   5594:         * Note that site_code_min has to be global as we can't pass an
                   5595:         * argument through hash_foreach().  The value 224 is taken from
                   5596:         * RFC 3942.
                   5597:         */
                   5598:        site_code_min = 224;
                   5599:        option_code_hash_foreach(u->code_hash, lowest_site_code);
                   5600:
                   5601:        if (site_code_min < 224) {
                   5602:                log_error("WARNING: site-local option codes less than 224 have "
                   5603:                          "been deprecated by RFC3942.  You have options "
                   5604:                          "listed in site local space %s that number as low as "
                   5605:                          "%d.  Please investigate if these should be declared "
                   5606:                          "as regular options rather than site-local options, "
                   5607:                          "or migrated up past 224.",
                   5608:                          u->name, site_code_min);
                   5609:        }
                   5610:
                   5611:        /*
                   5612:         * don't even bother logging, this is just silly, and never worked
                   5613:         * on any old version of software.
                   5614:         */
                   5615:        if (site_code_min < 128)
                   5616:                site_code_min = 128;
                   5617:
                   5618:        /*
                   5619:         * Cache the determined minimum site code on the universe structure.
                   5620:         * Note that due to the < 128 check above, a value of zero is
                   5621:         * impossible.
                   5622:         */
                   5623:        u->site_code_min = site_code_min;
                   5624:
                   5625:        return site_code_min;
                   5626: }
                   5627:
                   5628: static isc_result_t
                   5629: lowest_site_code(const void *key, unsigned len, void *object)
                   5630: {
                   5631:        struct option *option = object;
                   5632:
                   5633:        if (option->code < site_code_min)
                   5634:                site_code_min = option->code;
                   5635:
                   5636:        return ISC_R_SUCCESS;
                   5637: }
                   5638:
                   5639: static void
                   5640: maybe_return_agent_options(struct packet *packet, struct option_state *options)
                   5641: {
                   5642:        /* If there were agent options in the incoming packet, return
                   5643:         * them.  Do not return the agent options if they were stashed
                   5644:         * on the lease.  We do not check giaddr to detect the presence of
                   5645:         * a relay, as this excludes "l2" relay agents which have no giaddr
                   5646:         * to set.
                   5647:         *
                   5648:         * XXX: If the user configures options for the relay agent information
                   5649:         * (state->options->universes[agent_universe.index] is not NULL),
                   5650:         * we're still required to duplicate other values provided by the
                   5651:         * relay agent.  So we need to merge the old values not configured
                   5652:         * by the user into the new state, not just give up.
                   5653:         */
                   5654:        if (!packet->agent_options_stashed &&
                   5655:            (packet->options != NULL) &&
                   5656:            packet->options->universe_count > agent_universe.index &&
                   5657:            packet->options->universes[agent_universe.index] != NULL &&
                   5658:            (options->universe_count <= agent_universe.index ||
                   5659:             options->universes[agent_universe.index] == NULL)) {
                   5660:                option_chain_head_reference
                   5661:                    ((struct option_chain_head **)
                   5662:                     &(options->universes[agent_universe.index]),
                   5663:                     (struct option_chain_head *)
                   5664:                     packet->options->universes[agent_universe.index], MDL);
                   5665:
                   5666:                if (options->universe_count <= agent_universe.index)
                   5667:                        options->universe_count = agent_universe.index + 1;
                   5668:        }
                   5669: }
                   5670:
                   5671: /*!
                   5672:  * \brief Adds hostname option when use-host-decl-names is enabled.
                   5673:  *
                   5674:  * Constructs a hostname option from the name of the host declaration if
                   5675:  * there is one and no hostname has otherwise been provided and the
                   5676:  * use-host-decl-names flag is set, then adds the new option to the given
                   5677:  * option_state.  This funciton is used for both bootp and dhcp.
                   5678:  *
                   5679:  * \param packet inbound packet received from the client
                   5680:  * \param lease lease associated with the client
                   5681:  * \param options option state to search and update
                   5682:  */
                   5683: void use_host_decl_name(struct packet* packet,
                   5684:                        struct lease *lease,
                   5685:                        struct option_state *options) {
                   5686:        unsigned int ocode = SV_USE_HOST_DECL_NAMES;
                   5687:         if ((lease->host && lease->host->name) &&
                   5688:            !lookup_option(&dhcp_universe, options, DHO_HOST_NAME) &&
                   5689:             (evaluate_boolean_option_cache(NULL, packet, lease, NULL,
                   5690:                                           packet->options, options,
                   5691:                                           &lease->scope,
                   5692:                                           lookup_option(&server_universe,
                   5693:                                                         options, ocode),
                   5694:                                           MDL))) {
                   5695:                struct option_cache *oc = NULL;
                   5696:                 if (option_cache_allocate (&oc, MDL)) {
                   5697:                         if (make_const_data(&oc -> expression,
                   5698:                                             ((unsigned char*)lease->host->name),
                   5699:                                             strlen(lease->host->name),
                   5700:                                            1, 0, MDL)) {
                   5701:                                ocode = DHO_HOST_NAME;
                   5702:                                 option_code_hash_lookup(&oc->option,
                   5703:                                                         dhcp_universe.code_hash,
                   5704:                                                         &ocode, 0, MDL);
                   5705:                                 save_option(&dhcp_universe, options, oc);
                   5706:                         }
                   5707:                         option_cache_dereference(&oc, MDL);
                   5708:                 }
                   5709:         }
                   5710: }
                   5711:
                   5712: /*!
                   5713:  * \brief Checks and preps for lease resuse based on dhcp-cache-threshold
                   5714:  *
                   5715:  * If dhcp-cache-threshold is enabled (i.e. greater than zero), this function
                   5716:  * determines if the current lease is young enough to be reused.  If the lease
                   5717:  * can be resused the function returns 1, O if not.  This function is called
                   5718:  * by ack_lease when responding to both DISCOVERs and REQUESTS.
                   5719:  *
                   5720:  * The current lease can be reused only if all of the following are true:
                   5721:  *  a. dhcp-cache-threshold is > 0
                   5722:  *  b. The current lease is active
                   5723:  *  c. The lease "age" is less than that allowed by the threshold
                   5724:  *  d. DNS updates are not being performed on the new lease.
                   5725:  *  e. Lease has not been otherwise disqualified for reuse (Ex: billing class
                   5726:  *  or hostname changed)
                   5727:  *  f. The host declaration has changed (either a new one was added
                   5728:  *  or an older one was found due to something like a change in the uid)
                   5729:  *  g. The UID or hardware address have changed.
                   5730:  *
                   5731:  * Clients may renew leases using full DORA cycles or just RAs. This means
                   5732:  * that reusability must be checked when acking both DISCOVERs and REQUESTs.
                   5733:  * When a lease cannot be reused, ack_lease() calls supersede_lease() which
                   5734:  * updates the lease start time (among other things).  If this occurs on the
                   5735:  * DISCOVER, then the lease will virtually always be seen as young enough to
                   5736:  * reuse on the ensuing REQUEST and the lease updates will not get committed
                   5737:  * to the lease file.  The lease.cannot_reuse flag is used to handle this
                   5738:  * this situation.
                   5739:  *
                   5740:  * \param packet inbound packet received from the client
                   5741:  * \param new_lease candidate new lease to associate with the client
                   5742:  * \param lease current lease associated with the client
1.1.1.2   christos 5743:  * \param lease_state lease state to search and update
                   5744:  * \param offer type of DHCP response we're building
                   5745:  * \param[out] same_client pointer to int, that will be set to 1 if
                   5746:  * the two leases refer to the same client, 0 if not. Must NOT be null.
1.1       christos 5747:  *
                   5748:  * \return 1 if the lease can be reused.
                   5749:  */
                   5750: int
                   5751: reuse_lease (struct packet* packet,
                   5752:             struct lease* new_lease,
                   5753:             struct lease* lease,
                   5754:             struct lease_state *state,
1.1.1.2   christos 5755:             int offer,
                   5756:             int *same_client) {
1.1       christos 5757:        int reusable = 0;
                   5758:
                   5759:        /* To even consider reuse all of the following must be true:
                   5760:         * 1 - reuse hasn't already disqualified
                   5761:         * 2 - current lease is active
                   5762:         * 3 - DNS info hasn't changed
                   5763:         * 4 - the host declaration hasn't changed
                   5764:         * 5 - the uid hasn't changed
                   5765:         * 6 - the hardware address hasn't changed */
1.1.1.2   christos 5766:
                   5767:        /* Check client equality separately so we can pass the result out. */
                   5768:        *same_client =
                   5769:            (((lease->host == new_lease->host) &&
                   5770:              (lease->uid_len == new_lease->uid_len) &&
                   5771:              (memcmp(lease->uid, new_lease->uid, new_lease->uid_len) == 0) &&
                   5772:              (lease->hardware_addr.hlen == new_lease->hardware_addr.hlen) &&
                   5773:              (memcmp(&lease->hardware_addr.hbuf[0],
                   5774:                      &new_lease->hardware_addr.hbuf[0],
                   5775:                      lease->hardware_addr.hlen) == 0)) ? 1 : 0);
                   5776:
1.1       christos 5777:        if ((lease->cannot_reuse == 0) &&
                   5778:            (lease->binding_state == FTS_ACTIVE) &&
1.1.1.2   christos 5779:            (new_lease->ddns_cb == NULL) && *same_client) {
1.1       christos 5780:                int thresh = DEFAULT_CACHE_THRESHOLD;
                   5781:                struct option_cache* oc = NULL;
                   5782:                struct data_string d1;
                   5783:
                   5784:                /* Look up threshold value */
                   5785:                memset(&d1, 0, sizeof(struct data_string));
                   5786:                if ((oc = lookup_option(&server_universe, state->options,
                   5787:                                        SV_CACHE_THRESHOLD)) &&
                   5788:                     (evaluate_option_cache(&d1, packet, new_lease, NULL,
                   5789:                                      packet->options, state->options,
                   5790:                                      &new_lease->scope, oc, MDL))) {
                   5791:                        if (d1.len == 1 && (d1.data[0] < 100))
                   5792:                                thresh = d1.data[0];
                   5793:
                   5794:                        data_string_forget(&d1, MDL);
                   5795:                }
                   5796:
                   5797:                /* If threshold is enabled, check lease age */
                   5798:                if (thresh > 0) {
                   5799:                        int limit = 0;
                   5800:                        int lease_length = 0;
                   5801:                        long lease_age = 0;
                   5802:
                   5803:                        /* Calculate limit in seconds */
                   5804:                        lease_length = lease->ends - lease->starts;
                   5805:                        if (lease_length <= (INT_MAX / thresh))
                   5806:                                limit = lease_length * thresh / 100;
                   5807:                        else
                   5808:                                limit = lease_length / 100 * thresh;
                   5809:
                   5810:                        /* Note new_lease->starts is really just cur_time */
                   5811:                        lease_age = new_lease->starts - lease->starts;
                   5812:
                   5813:                        /* Is the lease young enough to reuse? */
                   5814:                        if (lease_age <= limit) {
                   5815:                                /* Restore expiry to its original value */
                   5816:                                state->offered_expiry = lease->ends;
                   5817:
                   5818:                                /* Restore bindings. This fixes 37368. */
                   5819:                                if (new_lease->scope != NULL) {
                   5820:                                        if (lease->scope != NULL) {
                   5821:                                                binding_scope_dereference(
                   5822:                                                                &lease->scope,
                   5823:                                                                MDL);
                   5824:                                        }
                   5825:
                   5826:                                        binding_scope_reference(&lease->scope,
                   5827:                                                        new_lease->scope, MDL);
                   5828:                                }
                   5829:
                   5830:                                /* restore client hostname, fixes 42849. */
                   5831:                                if (new_lease->client_hostname) {
                   5832:                                        lease->client_hostname =
                   5833:                                          new_lease->client_hostname;
                   5834:                                        new_lease->client_hostname = NULL;
                   5835:                                }
                   5836:
                   5837:                                /* We're cleared to reuse it */
                   5838:                                log_debug("reuse_lease: lease age %ld (secs)"
                   5839:                                          " under %d%% threshold, reply with "
                   5840:                                          "unaltered, existing lease for %s",
                   5841:                                          lease_age, thresh, piaddr(lease->ip_addr));
                   5842:
                   5843:                                reusable = 1;
                   5844:                        }
                   5845:                }
                   5846:        }
                   5847:
                   5848:        /* If we can't reuse it and this is an offer disqualify reuse for
                   5849:         * ensuing REQUEST, otherwise clear the flag. */
                   5850:        lease->cannot_reuse = (!reusable && offer == DHCPOFFER);
                   5851:        return (reusable);
                   5852: }
                   5853:
                   5854: /* \brief Validates a proposed value for use as a lease time
                   5855:  *
                   5856:  * Convenience function used for catching calculeated lease
                   5857:  * times that overflow 4-byte times used in v4 protocol.
                   5858:  *
                   5859:  * We use variables of type TIME in lots of places, which on
                   5860:  * 64-bit systems is 8 bytes while on 32-bit OSs it is int32_t,
                   5861:  * so we have all sorts of fun places to mess things up.
                   5862:  * This function checks a calculated lease time for and if it
                   5863:  * is unsuitable for use as a lease time, the given alternate
                   5864:  * value is returned.
                   5865:  * \param calculated
                   5866:  * \param alternate
                   5867:  *
                   5868:  * \returen either the calculated value if it is valid, or
                   5869:  * the alternate value supplied
                   5870:  */
                   5871: TIME leaseTimeCheck(TIME calculated, TIME alternate) {
                   5872:     if ((sizeof(TIME) > 4 && calculated >= INFINITE_TIME) ||
                   5873:         (calculated < cur_time)) {
                   5874:         return (alternate);
                   5875:     }
                   5876:
                   5877:     return (calculated);
                   5878: }

CVSweb <webmaster@jp.NetBSD.org>