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 (<, 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, <->ip_addr.iabuf, 4);
2843: nak_lease(packet, &cip, lease->subnet->group);
2844: free_lease_state (state, MDL);
2845: lease_dereference (<, 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, <->ip_addr.iabuf, 4);
2873: nak_lease(packet, &cip, lease->subnet->group);
2874: free_lease_state (state, MDL);
2875: lease_dereference (<, 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 (< -> host, host, MDL);
3054: host_dereference (&host, MDL);
3055: }
3056: if (lease -> subnet)
3057: subnet_reference (< -> subnet, lease -> subnet, MDL);
3058: if (lease -> billing_class)
3059: class_reference (< -> 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 (< -> scope, lease -> scope, MDL);
3072: binding_scope_dereference (&lease -> scope, MDL);
3073: }
3074: if (lease -> agent_options)
3075: option_chain_head_reference (< -> 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, <->scope, oc, MDL)) {
3084: if (d1.len != 0) {
3085: bind_ds_value(<->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 (< -> agent_options, MDL);
3112: option_chain_head_reference
3113: (< -> 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 (< -> 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, <->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: < -> 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 (<, MDL);
3251: return;
3252: }
3253: }
3254: lease_dereference (<, 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>