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