Nuke unused macro and comment
[dragonfly.git] / contrib / dhcp-3.0 / server / dhcp.c
blob8e1a48cf609b0d9cb73e64cd41980e252aa7b502
1 /* dhcp.c
3 DHCP Protocol engine. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
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 * ``http://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''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: dhcp.c,v 1.192.2.44 2004/11/24 17:39:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
42 int outstanding_pings;
44 static char dhcp_message [256];
46 static const char *dhcp_type_names [] = {
47 "DHCPDISCOVER",
48 "DHCPOFFER",
49 "DHCPREQUEST",
50 "DHCPDECLINE",
51 "DHCPACK",
52 "DHCPNAK",
53 "DHCPRELEASE",
54 "DHCPINFORM"
56 const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
58 #if defined (TRACING)
59 # define send_packet trace_packet_send
60 #endif
62 void dhcp (packet)
63 struct packet *packet;
65 int ms_nulltp = 0;
66 struct option_cache *oc;
67 struct lease *lease = (struct lease *)0;
68 const char *errmsg;
69 struct data_string data;
71 if (!locate_network (packet) &&
72 packet -> packet_type != DHCPREQUEST &&
73 packet -> packet_type != DHCPINFORM) {
74 const char *s;
75 char typebuf [32];
76 errmsg = "unknown network segment";
77 bad_packet:
79 if (packet -> packet_type > 0 &&
80 packet -> packet_type < dhcp_type_name_max - 1) {
81 s = dhcp_type_names [packet -> packet_type - 1];
82 } else {
83 /* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
84 sprintf (typebuf, "type %d", packet -> packet_type);
85 s = typebuf;
88 log_info ("%s from %s via %s: %s", s,
89 (packet -> raw -> htype
90 ? print_hw_addr (packet -> raw -> htype,
91 packet -> raw -> hlen,
92 packet -> raw -> chaddr)
93 : "<no identifier>"),
94 packet -> raw -> giaddr.s_addr
95 ? inet_ntoa (packet -> raw -> giaddr)
96 : packet -> interface -> name, errmsg);
97 goto out;
100 /* There is a problem with the relay agent information option,
101 which is that in order for a normal relay agent to append
102 this option, the relay agent has to have been involved in
103 getting the packet from the client to the server. Note
104 that this is the software entity known as the relay agent,
105 _not_ the hardware entity known as a router in which the
106 relay agent may be running, so the fact that a router has
107 forwarded a packet does not mean that the relay agent in
108 the router was involved.
110 So when the client is in INIT or INIT-REBOOT or REBINDING
111 state, the relay agent gets to tack on its options, but
112 when it's not, the relay agent doesn't get to do this,
113 which means that any decisions the DHCP server may make
114 based on the agent options will be made incorrectly.
116 We work around this in the following way: if this is a
117 DHCPREQUEST and doesn't have relay agent information
118 options, we see if there's an existing lease for this IP
119 address and this client that _does_ have stashed agent
120 options. If so, then we tack those options onto the
121 packet as if they came from the client. Later on, when we
122 are deciding whether to steal the agent options from the
123 packet, if the agent options stashed on the lease are the
124 same as those stashed on the packet, we don't steal them -
125 this ensures that the client never receives its agent
126 options. */
128 if (packet -> packet_type == DHCPREQUEST &&
129 packet -> raw -> ciaddr.s_addr &&
130 !packet -> raw -> giaddr.s_addr &&
131 (packet -> options -> universe_count < agent_universe.index ||
132 !packet -> options -> universes [agent_universe.index]))
134 struct iaddr cip;
136 cip.len = sizeof packet -> raw -> ciaddr;
137 memcpy (cip.iabuf, &packet -> raw -> ciaddr,
138 sizeof packet -> raw -> ciaddr);
139 if (!find_lease_by_ip_addr (&lease, cip, MDL))
140 goto nolease;
142 /* If there are no agent options on the lease, it's not
143 interesting. */
144 if (!lease -> agent_options)
145 goto nolease;
147 /* The client should not be unicasting a renewal if its lease
148 has expired, so make it go through the process of getting
149 its agent options legally. */
150 if (lease -> ends < cur_time)
151 goto nolease;
153 if (lease -> uid_len) {
154 oc = lookup_option (&dhcp_universe, packet -> options,
155 DHO_DHCP_CLIENT_IDENTIFIER);
156 if (!oc)
157 goto nolease;
159 memset (&data, 0, sizeof data);
160 if (!evaluate_option_cache (&data,
161 packet, (struct lease *)0,
162 (struct client_state *)0,
163 packet -> options,
164 (struct option_state *)0,
165 &global_scope, oc, MDL))
166 goto nolease;
167 if (lease -> uid_len != data.len ||
168 memcmp (lease -> uid, data.data, data.len)) {
169 data_string_forget (&data, MDL);
170 goto nolease;
172 data_string_forget (&data, MDL);
173 } else
174 if ((lease -> hardware_addr.hbuf [0] !=
175 packet -> raw -> htype) ||
176 (lease -> hardware_addr.hlen - 1 !=
177 packet -> raw -> hlen) ||
178 memcmp (&lease -> hardware_addr.hbuf [1],
179 packet -> raw -> chaddr,
180 packet -> raw -> hlen))
181 goto nolease;
183 /* Okay, so we found a lease that matches the client. */
184 option_chain_head_reference ((struct option_chain_head **)
185 &(packet -> options -> universes
186 [agent_universe.index]),
187 lease -> agent_options, MDL);
189 nolease:
191 /* Classify the client. */
192 if ((oc = lookup_option (&dhcp_universe, packet -> options,
193 DHO_HOST_NAME))) {
194 if (!oc -> expression)
195 while (oc -> data.len &&
196 oc -> data.data [oc -> data.len - 1] == 0) {
197 ms_nulltp = 1;
198 oc -> data.len--;
202 classify_client (packet);
204 switch (packet -> packet_type) {
205 case DHCPDISCOVER:
206 dhcpdiscover (packet, ms_nulltp);
207 break;
209 case DHCPREQUEST:
210 dhcprequest (packet, ms_nulltp, lease);
211 break;
213 case DHCPRELEASE:
214 dhcprelease (packet, ms_nulltp);
215 break;
217 case DHCPDECLINE:
218 dhcpdecline (packet, ms_nulltp);
219 break;
221 case DHCPINFORM:
222 dhcpinform (packet, ms_nulltp);
223 break;
226 case DHCPACK:
227 case DHCPOFFER:
228 case DHCPNAK:
229 break;
231 default:
232 errmsg = "unknown packet type";
233 goto bad_packet;
235 out:
236 if (lease)
237 lease_dereference (&lease, MDL);
240 void dhcpdiscover (packet, ms_nulltp)
241 struct packet *packet;
242 int ms_nulltp;
244 struct lease *lease = (struct lease *)0;
245 char msgbuf [1024]; /* XXX */
246 TIME when;
247 const char *s;
248 int allocatedp = 0;
249 int peer_has_leases = 0;
250 int alloc_lease_called = 0;
251 #if defined (FAILOVER_PROTOCOL)
252 dhcp_failover_state_t *peer;
253 #endif
255 find_lease (&lease, packet, packet -> shared_network,
256 0, &allocatedp, (struct lease *)0, MDL);
258 if (lease && lease -> client_hostname) {
259 if ((strlen (lease -> client_hostname) <= 64) &&
260 db_printable (lease -> client_hostname))
261 s = lease -> client_hostname;
262 else
263 s = "Hostname Unsuitable for Printing";
264 } else
265 s = (char *)0;
267 /* %Audit% This is log output. %2004.06.17,Safe%
268 * If we truncate we hope the user can get a hint from the log.
270 snprintf (msgbuf, sizeof msgbuf, "DHCPDISCOVER from %s %s%s%svia %s",
271 (packet -> raw -> htype
272 ? print_hw_addr (packet -> raw -> htype,
273 packet -> raw -> hlen,
274 packet -> raw -> chaddr)
275 : (lease
276 ? print_hex_1 (lease -> uid_len, lease -> uid,
277 lease -> uid_len)
278 : "<no identifier>")),
279 s ? "(" : "", s ? s : "", s ? ") " : "",
280 packet -> raw -> giaddr.s_addr
281 ? inet_ntoa (packet -> raw -> giaddr)
282 : packet -> interface -> name);
284 /* Sourceless packets don't make sense here. */
285 if (!packet -> shared_network) {
286 log_info ("Packet from unknown subnet: %s",
287 inet_ntoa (packet -> raw -> giaddr));
288 goto out;
291 #if defined (FAILOVER_PROTOCOL)
292 if (lease && lease -> pool && lease -> pool -> failover_peer) {
293 peer = lease -> pool -> failover_peer;
295 /* If the lease is ours to allocate, then allocate it,
296 but set the allocatedp flag. */
297 if (lease_mine_to_reallocate (lease))
298 allocatedp = 1;
300 /* If the lease is active, do load balancing to see who
301 allocates the lease (if it's active, it already belongs
302 to the client, or we wouldn't have gotten it from
303 find_lease (). */
304 else if (lease -> binding_state == FTS_ACTIVE &&
305 (peer -> service_state != cooperating ||
306 load_balance_mine (packet, peer)))
309 /* Otherwise, we can't let the client have this lease. */
310 else {
311 #if defined (DEBUG_FIND_LEASE)
312 log_debug ("discarding %s - %s",
313 piaddr (lease -> ip_addr),
314 binding_state_print (lease -> binding_state));
315 #endif
316 lease_dereference (&lease, MDL);
319 #endif
321 /* If we didn't find a lease, try to allocate one... */
322 if (!lease) {
323 if (!allocate_lease (&lease, packet,
324 packet -> shared_network -> pools,
325 &peer_has_leases)) {
326 if (peer_has_leases)
327 log_error ("%s: peer holds all free leases",
328 msgbuf);
329 else
330 log_error ("%s: network %s: no free leases",
331 msgbuf,
332 packet -> shared_network -> name);
333 return;
335 #if defined (FAILOVER_PROTOCOL)
336 if (lease -> pool && lease -> pool -> failover_peer)
337 dhcp_failover_pool_check (lease -> pool);
338 #endif
339 allocatedp = 1;
340 alloc_lease_called = 1;
343 #if defined (FAILOVER_PROTOCOL)
344 if (lease && lease -> pool && lease -> pool -> failover_peer) {
345 peer = lease -> pool -> failover_peer;
346 if (peer -> service_state == not_responding ||
347 peer -> service_state == service_startup) {
348 log_info ("%s: not responding%s",
349 msgbuf, peer -> nrr);
350 goto out;
352 } else
353 peer = (dhcp_failover_state_t *)0;
355 /* Do load balancing if configured. */
356 /* If the lease is newly allocated, and we're not the server that
357 the client would normally get with load balancing, and the
358 failover protocol state is normal, let the other server get this.
359 XXX Check protocol spec to make sure that predicating this on
360 XXX allocatedp is okay - I'm doing this so that the client won't
361 XXX be forced to switch servers (and IP addresses) just because
362 XXX of bad luck, when it's possible for it to get the address it
363 XXX is requesting. Not sure this is allowed. */
364 if (allocatedp && peer && (peer -> service_state == cooperating) &&
365 !load_balance_mine (packet, peer)) {
366 /* peer_has_leases only has a chance to be set if we called
367 * allocate_lease() above.
369 if (!alloc_lease_called || peer_has_leases) {
370 log_debug ("%s: load balance to peer %s",
371 msgbuf, peer -> name);
372 goto out;
373 } else {
374 log_debug ("cancel load balance to peer %s - %s",
375 peer -> name, "no free leases");
378 #endif
380 /* If it's an expired lease, get rid of any bindings. */
381 if (lease -> ends < cur_time && lease -> scope)
382 binding_scope_dereference (&lease -> scope, MDL);
384 /* Set the lease to really expire in 2 minutes, unless it has
385 not yet expired, in which case leave its expiry time alone. */
386 when = cur_time + 120;
387 if (when < lease -> ends)
388 when = lease -> ends;
390 ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp);
391 out:
392 if (lease)
393 lease_dereference (&lease, MDL);
396 void dhcprequest (packet, ms_nulltp, ip_lease)
397 struct packet *packet;
398 int ms_nulltp;
399 struct lease *ip_lease;
401 struct lease *lease;
402 struct iaddr cip;
403 struct iaddr sip;
404 struct subnet *subnet;
405 int ours = 0;
406 struct option_cache *oc;
407 struct data_string data;
408 int status;
409 char msgbuf [1024]; /* XXX */
410 const char *s;
411 char smbuf [19];
412 #if defined (FAILOVER_PROTOCOL)
413 dhcp_failover_state_t *peer;
414 #endif
415 int have_server_identifier = 0;
416 int have_requested_addr = 0;
418 oc = lookup_option (&dhcp_universe, packet -> options,
419 DHO_DHCP_REQUESTED_ADDRESS);
420 memset (&data, 0, sizeof data);
421 if (oc &&
422 evaluate_option_cache (&data, packet, (struct lease *)0,
423 (struct client_state *)0,
424 packet -> options, (struct option_state *)0,
425 &global_scope, oc, MDL)) {
426 cip.len = 4;
427 memcpy (cip.iabuf, data.data, 4);
428 data_string_forget (&data, MDL);
429 have_requested_addr = 1;
430 } else {
431 oc = (struct option_cache *)0;
432 cip.len = 4;
433 memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
436 /* Find the lease that matches the address requested by the
437 client. */
439 subnet = (struct subnet *)0;
440 lease = (struct lease *)0;
441 if (find_subnet (&subnet, cip, MDL))
442 find_lease (&lease, packet,
443 subnet -> shared_network, &ours, 0, ip_lease, MDL);
444 /* XXX consider using allocatedp arg to find_lease to see
445 XXX that this isn't a compliant DHCPREQUEST. */
447 if (lease && lease -> client_hostname) {
448 if ((strlen (lease -> client_hostname) <= 64) &&
449 db_printable (lease -> client_hostname))
450 s = lease -> client_hostname;
451 else
452 s = "Hostname Unsuitable for Printing";
453 } else
454 s = (char *)0;
456 oc = lookup_option (&dhcp_universe, packet -> options,
457 DHO_DHCP_SERVER_IDENTIFIER);
458 memset (&data, 0, sizeof data);
459 if (oc &&
460 evaluate_option_cache (&data, packet, (struct lease *)0,
461 (struct client_state *)0,
462 packet -> options, (struct option_state *)0,
463 &global_scope, oc, MDL)) {
464 sip.len = 4;
465 memcpy (sip.iabuf, data.data, 4);
466 data_string_forget (&data, MDL);
467 /* piaddr() should not return more than a 15 byte string.
468 * safe.
470 sprintf (smbuf, " (%s)", piaddr (sip));
471 have_server_identifier = 1;
472 } else
473 smbuf [0] = 0;
475 /* %Audit% This is log output. %2004.06.17,Safe%
476 * If we truncate we hope the user can get a hint from the log.
478 snprintf (msgbuf, sizeof msgbuf,
479 "DHCPREQUEST for %s%s from %s %s%s%svia %s",
480 piaddr (cip), smbuf,
481 (packet -> raw -> htype
482 ? print_hw_addr (packet -> raw -> htype,
483 packet -> raw -> hlen,
484 packet -> raw -> chaddr)
485 : (lease
486 ? print_hex_1 (lease -> uid_len, lease -> uid,
487 lease -> uid_len)
488 : "<no identifier>")),
489 s ? "(" : "", s ? s : "", s ? ") " : "",
490 packet -> raw -> giaddr.s_addr
491 ? inet_ntoa (packet -> raw -> giaddr)
492 : packet -> interface -> name);
494 #if defined (FAILOVER_PROTOCOL)
495 if (lease && lease -> pool && lease -> pool -> failover_peer) {
496 peer = lease -> pool -> failover_peer;
497 if (peer -> service_state == not_responding ||
498 peer -> service_state == service_startup) {
499 log_info ("%s: not responding%s",
500 msgbuf, peer -> nrr);
501 goto out;
503 /* Don't load balance if the client is RENEWING or REBINDING.
504 If it's RENEWING, we are the only server to hear it, so
505 we have to serve it. If it's REBINDING, it's out of
506 communication with the other server, so there's no point
507 in waiting to serve it. However, if the lease we're
508 offering is not a free lease, then we may be the only
509 server that can offer it, so we can't load balance if
510 the lease isn't in the free or backup state. */
511 if (peer -> service_state == cooperating &&
512 !packet -> raw -> ciaddr.s_addr &&
513 (lease -> binding_state == FTS_FREE ||
514 lease -> binding_state == FTS_BACKUP)) {
515 if (!load_balance_mine (packet, peer)) {
516 log_debug ("%s: load balance to peer %s",
517 msgbuf, peer -> name);
518 goto out;
522 /* Don't let a client allocate a lease using DHCPREQUEST
523 if the lease isn't ours to allocate. */
524 if ((lease -> binding_state == FTS_FREE ||
525 lease -> binding_state == FTS_BACKUP) &&
526 !lease_mine_to_reallocate (lease)) {
527 log_debug ("%s: lease owned by peer", msgbuf);
528 goto out;
531 /* If the lease is in a transitional state, we can't
532 renew it. */
533 if ((lease -> binding_state == FTS_RELEASED ||
534 lease -> binding_state == FTS_EXPIRED) &&
535 !lease_mine_to_reallocate (lease)) {
536 log_debug ("%s: lease in transition state %s", msgbuf,
537 lease -> binding_state == FTS_RELEASED
538 ? "released" : "expired");
539 goto out;
542 /* It's actually very unlikely that we'll ever get here,
543 but if we do, tell the client to stop using the lease,
544 because the administrator reset it. */
545 if (lease -> binding_state == FTS_RESET &&
546 !lease_mine_to_reallocate (lease)) {
547 log_debug ("%s: lease reset by administrator", msgbuf);
548 nak_lease (packet, &cip);
549 goto out;
552 /* At this point it's possible that we will get a broadcast
553 DHCPREQUEST for a lease that we didn't offer, because
554 both we and the peer are in a position to offer it.
555 In that case, we probably shouldn't answer. In order
556 to not answer, we would have to compare the server
557 identifier sent by the client with the list of possible
558 server identifiers we can send, and if the client's
559 identifier isn't on the list, drop the DHCPREQUEST.
560 We aren't currently doing that for two reasons - first,
561 it's not clear that all clients do the right thing
562 with respect to sending the client identifier, which
563 could mean that we might simply not respond to a client
564 that is depending on us to respond. Secondly, we allow
565 the user to specify the server identifier to send, and
566 we don't enforce that the server identifier should be
567 one of our IP addresses. This is probably not a big
568 deal, but it's theoretically an issue.
570 The reason we care about this is that if both servers
571 send a DHCPACK to the DHCPREQUEST, they are then going
572 to send dueling BNDUPD messages, which could cause
573 trouble. I think it causes no harm, but it seems
574 wrong. */
575 } else
576 peer = (dhcp_failover_state_t *)0;
577 #endif
579 /* If a client on a given network REQUESTs a lease on an
580 address on a different network, NAK it. If the Requested
581 Address option was used, the protocol says that it must
582 have been broadcast, so we can trust the source network
583 information.
585 If ciaddr was specified and Requested Address was not, then
586 we really only know for sure what network a packet came from
587 if it came through a BOOTP gateway - if it came through an
588 IP router, we'll just have to assume that it's cool.
590 If we don't think we know where the packet came from, it
591 came through a gateway from an unknown network, so it's not
592 from a RENEWING client. If we recognize the network it
593 *thinks* it's on, we can NAK it even though we don't
594 recognize the network it's *actually* on; otherwise we just
595 have to ignore it.
597 We don't currently try to take advantage of access to the
598 raw packet, because it's not available on all platforms.
599 So a packet that was unicast to us through a router from a
600 RENEWING client is going to look exactly like a packet that
601 was broadcast to us from an INIT-REBOOT client.
603 Since we can't tell the difference between these two kinds
604 of packets, if the packet appears to have come in off the
605 local wire, we have to treat it as if it's a RENEWING
606 client. This means that we can't NAK a RENEWING client on
607 the local wire that has a bogus address. The good news is
608 that we won't ACK it either, so it should revert to INIT
609 state and send us a DHCPDISCOVER, which we *can* work with.
611 Because we can't detect that a RENEWING client is on the
612 wrong wire, it's going to sit there trying to renew until
613 it gets to the REBIND state, when we *can* NAK it because
614 the packet will get to us through a BOOTP gateway. We
615 shouldn't actually see DHCPREQUEST packets from RENEWING
616 clients on the wrong wire anyway, since their idea of their
617 local router will be wrong. In any case, the protocol
618 doesn't really allow us to NAK a DHCPREQUEST from a
619 RENEWING client, so we can punt on this issue. */
621 if (!packet -> shared_network ||
622 (packet -> raw -> ciaddr.s_addr &&
623 packet -> raw -> giaddr.s_addr) ||
624 (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
626 /* If we don't know where it came from but we do know
627 where it claims to have come from, it didn't come
628 from there. */
629 if (!packet -> shared_network) {
630 if (subnet && subnet -> group -> authoritative) {
631 log_info ("%s: wrong network.", msgbuf);
632 nak_lease (packet, &cip);
633 goto out;
635 /* Otherwise, ignore it. */
636 log_info ("%s: ignored (%s).", msgbuf,
637 (subnet
638 ? "not authoritative" : "unknown subnet"));
639 goto out;
642 /* If we do know where it came from and it asked for an
643 address that is not on that shared network, nak it. */
644 if (subnet)
645 subnet_dereference (&subnet, MDL);
646 if (!find_grouped_subnet (&subnet, packet -> shared_network,
647 cip, MDL)) {
648 if (packet -> shared_network -> group -> authoritative)
650 log_info ("%s: wrong network.", msgbuf);
651 nak_lease (packet, &cip);
652 goto out;
654 log_info ("%s: ignored (not authoritative).", msgbuf);
655 return;
659 /* If the address the client asked for is ours, but it wasn't
660 available for the client, NAK it. */
661 if (!lease && ours) {
662 log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
663 nak_lease (packet, &cip);
664 goto out;
667 /* Otherwise, send the lease to the client if we found one. */
668 if (lease) {
669 ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp);
670 } else
671 log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
673 out:
674 if (subnet)
675 subnet_dereference (&subnet, MDL);
676 if (lease)
677 lease_dereference (&lease, MDL);
678 return;
681 void dhcprelease (packet, ms_nulltp)
682 struct packet *packet;
683 int ms_nulltp;
685 struct lease *lease = (struct lease *)0, *next = (struct lease *)0;
686 struct iaddr cip;
687 struct option_cache *oc;
688 struct data_string data;
689 const char *s;
690 char msgbuf [1024], cstr[16]; /* XXX */
693 /* DHCPRELEASE must not specify address in requested-address
694 option, but old protocol specs weren't explicit about this,
695 so let it go. */
696 if ((oc = lookup_option (&dhcp_universe, packet -> options,
697 DHO_DHCP_REQUESTED_ADDRESS))) {
698 log_info ("DHCPRELEASE from %s specified requested-address.",
699 print_hw_addr (packet -> raw -> htype,
700 packet -> raw -> hlen,
701 packet -> raw -> chaddr));
704 oc = lookup_option (&dhcp_universe, packet -> options,
705 DHO_DHCP_CLIENT_IDENTIFIER);
706 memset (&data, 0, sizeof data);
707 if (oc &&
708 evaluate_option_cache (&data, packet, (struct lease *)0,
709 (struct client_state *)0,
710 packet -> options, (struct option_state *)0,
711 &global_scope, oc, MDL)) {
712 find_lease_by_uid (&lease, data.data, data.len, MDL);
713 data_string_forget (&data, MDL);
715 /* See if we can find a lease that matches the IP address
716 the client is claiming. */
717 while (lease) {
718 if (lease -> n_uid)
719 lease_reference (&next, lease -> n_uid, MDL);
720 if (!memcmp (&packet -> raw -> ciaddr,
721 lease -> ip_addr.iabuf, 4)) {
722 break;
724 lease_dereference (&lease, MDL);
725 if (next) {
726 lease_reference (&lease, next, MDL);
727 lease_dereference (&next, MDL);
730 if (next)
731 lease_dereference (&next, MDL);
734 /* The client is supposed to pass a valid client-identifier,
735 but the spec on this has changed historically, so try the
736 IP address in ciaddr if the client-identifier fails. */
737 if (!lease) {
738 cip.len = 4;
739 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
740 find_lease_by_ip_addr (&lease, cip, MDL);
744 /* If the hardware address doesn't match, don't do the release. */
745 if (lease &&
746 (lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
747 lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
748 memcmp (&lease -> hardware_addr.hbuf [1],
749 packet -> raw -> chaddr, packet -> raw -> hlen)))
750 lease_dereference (&lease, MDL);
752 if (lease && lease -> client_hostname) {
753 if ((strlen (lease -> client_hostname) <= 64) &&
754 db_printable (lease -> client_hostname))
755 s = lease -> client_hostname;
756 else
757 s = "Hostname Unsuitable for Printing";
758 } else
759 s = (char *)0;
761 /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe%
762 * We copy this out to stack because we actually want to log two
763 * inet_ntoa()'s in this message.
765 strncpy(cstr, inet_ntoa (packet -> raw -> ciaddr), 15);
766 cstr[15] = '\0';
768 /* %Audit% This is log output. %2004.06.17,Safe%
769 * If we truncate we hope the user can get a hint from the log.
771 snprintf (msgbuf, sizeof msgbuf,
772 "DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
773 cstr,
774 (packet -> raw -> htype
775 ? print_hw_addr (packet -> raw -> htype,
776 packet -> raw -> hlen,
777 packet -> raw -> chaddr)
778 : (lease
779 ? print_hex_1 (lease -> uid_len, lease -> uid,
780 lease -> uid_len)
781 : "<no identifier>")),
782 s ? "(" : "", s ? s : "", s ? ") " : "",
783 packet -> raw -> giaddr.s_addr
784 ? inet_ntoa (packet -> raw -> giaddr)
785 : packet -> interface -> name,
786 lease ? "" : "not ");
788 #if defined (FAILOVER_PROTOCOL)
789 if (lease && lease -> pool && lease -> pool -> failover_peer) {
790 dhcp_failover_state_t *peer = lease -> pool -> failover_peer;
791 if (peer -> service_state == not_responding ||
792 peer -> service_state == service_startup) {
793 log_info ("%s: ignored%s",
794 peer -> name, peer -> nrr);
795 goto out;
798 /* DHCPRELEASE messages are unicast, so if the client
799 sent the DHCPRELEASE to us, it's not going to send it
800 to the peer. Not sure why this would happen, and
801 if it does happen I think we still have to change the
802 lease state, so that's what we're doing.
803 XXX See what it says in the draft about this. */
805 #endif
807 /* If we found a lease, release it. */
808 if (lease && lease -> ends > cur_time) {
809 release_lease (lease, packet);
811 log_info ("%s", msgbuf);
812 out:
813 if (lease)
814 lease_dereference (&lease, MDL);
817 void dhcpdecline (packet, ms_nulltp)
818 struct packet *packet;
819 int ms_nulltp;
821 struct lease *lease = (struct lease *)0;
822 struct option_state *options = (struct option_state *)0;
823 int ignorep = 0;
824 int i;
825 const char *status;
826 const char *s;
827 char msgbuf [1024]; /* XXX */
828 struct iaddr cip;
829 struct option_cache *oc;
830 struct data_string data;
832 /* DHCPDECLINE must specify address. */
833 if (!(oc = lookup_option (&dhcp_universe, packet -> options,
834 DHO_DHCP_REQUESTED_ADDRESS)))
835 return;
836 memset (&data, 0, sizeof data);
837 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
838 (struct client_state *)0,
839 packet -> options,
840 (struct option_state *)0,
841 &global_scope, oc, MDL))
842 return;
844 cip.len = 4;
845 memcpy (cip.iabuf, data.data, 4);
846 data_string_forget (&data, MDL);
847 find_lease_by_ip_addr (&lease, cip, MDL);
849 if (lease && lease -> client_hostname) {
850 if ((strlen (lease -> client_hostname) <= 64) &&
851 db_printable (lease -> client_hostname))
852 s = lease -> client_hostname;
853 else
854 s = "Hostname Unsuitable for Printing";
855 } else
856 s = (char *)0;
858 /* %Audit% This is log output. %2004.06.17,Safe%
859 * If we truncate we hope the user can get a hint from the log.
861 snprintf (msgbuf, sizeof msgbuf,
862 "DHCPDECLINE of %s from %s %s%s%svia %s",
863 piaddr (cip),
864 (packet -> raw -> htype
865 ? print_hw_addr (packet -> raw -> htype,
866 packet -> raw -> hlen,
867 packet -> raw -> chaddr)
868 : (lease
869 ? print_hex_1 (lease -> uid_len, lease -> uid,
870 lease -> uid_len)
871 : "<no identifier>")),
872 s ? "(" : "", s ? s : "", s ? ") " : "",
873 packet -> raw -> giaddr.s_addr
874 ? inet_ntoa (packet -> raw -> giaddr)
875 : packet -> interface -> name);
877 option_state_allocate (&options, MDL);
879 /* Execute statements in scope starting with the subnet scope. */
880 if (lease)
881 execute_statements_in_scope ((struct binding_value **)0,
882 packet, (struct lease *)0,
883 (struct client_state *)0,
884 packet -> options, options,
885 &global_scope,
886 lease -> subnet -> group,
887 (struct group *)0);
889 /* Execute statements in the class scopes. */
890 for (i = packet -> class_count; i > 0; i--) {
891 execute_statements_in_scope
892 ((struct binding_value **)0, packet, (struct lease *)0,
893 (struct client_state *)0, packet -> options, options,
894 &global_scope, packet -> classes [i - 1] -> group,
895 lease ? lease -> subnet -> group : (struct group *)0);
898 /* Drop the request if dhcpdeclines are being ignored. */
899 oc = lookup_option (&server_universe, options, SV_DECLINES);
900 if (!oc ||
901 evaluate_boolean_option_cache (&ignorep, packet, lease,
902 (struct client_state *)0,
903 packet -> options, options,
904 &lease -> scope, oc, MDL)) {
905 /* If we found a lease, mark it as unusable and complain. */
906 if (lease) {
907 #if defined (FAILOVER_PROTOCOL)
908 if (lease -> pool && lease -> pool -> failover_peer) {
909 dhcp_failover_state_t *peer =
910 lease -> pool -> failover_peer;
911 if (peer -> service_state == not_responding ||
912 peer -> service_state == service_startup) {
913 if (!ignorep)
914 log_info ("%s: ignored%s",
915 peer -> name, peer -> nrr);
916 goto out;
919 /* DHCPDECLINE messages are broadcast, so we can safely
920 ignore the DHCPDECLINE if the peer has the lease.
921 XXX Of course, at this point that information has been
922 lost. */
924 #endif
926 abandon_lease (lease, "declined.");
927 status = "abandoned";
929 status = "not found";
930 } else
931 status = "ignored";
933 if (!ignorep)
934 log_info ("%s: %s", msgbuf, status);
936 out:
937 if (options)
938 option_state_dereference (&options, MDL);
939 if (lease)
940 lease_dereference (&lease, MDL);
943 void dhcpinform (packet, ms_nulltp)
944 struct packet *packet;
945 int ms_nulltp;
947 char msgbuf [1024];
948 struct data_string d1, prl;
949 struct option_cache *oc;
950 struct expression *expr;
951 struct option_state *options = (struct option_state *)0;
952 struct dhcp_packet raw;
953 struct packet outgoing;
954 unsigned char dhcpack = DHCPACK;
955 struct subnet *subnet = (struct subnet *)0;
956 struct iaddr cip;
957 unsigned i, j;
958 int nulltp;
959 struct sockaddr_in to;
960 struct in_addr from;
962 /* The client should set ciaddr to its IP address, but apparently
963 it's common for clients not to do this, so we'll use their IP
964 source address if they didn't set ciaddr. */
965 if (!packet -> raw -> ciaddr.s_addr) {
966 cip.len = 4;
967 memcpy (cip.iabuf, &packet -> client_addr.iabuf, 4);
968 } else {
969 cip.len = 4;
970 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
973 /* %Audit% This is log output. %2004.06.17,Safe%
974 * If we truncate we hope the user can get a hint from the log.
976 snprintf (msgbuf, sizeof msgbuf, "DHCPINFORM from %s via %s",
977 piaddr (cip), packet -> interface -> name);
979 /* If the IP source address is zero, don't respond. */
980 if (!memcmp (cip.iabuf, "\0\0\0", 4)) {
981 log_info ("%s: ignored (null source address).", msgbuf);
982 return;
985 /* Find the subnet that the client is on. */
986 oc = (struct option_cache *)0;
987 find_subnet (&subnet , cip, MDL);
989 /* Sourceless packets don't make sense here. */
990 if (!subnet) {
991 log_info ("%s: unknown subnet %s",
992 msgbuf, inet_ntoa (packet -> raw -> giaddr));
993 return;
996 /* We don't respond to DHCPINFORM packets if we're not authoritative.
997 It would be nice if a per-host value could override this, but
998 there's overhead involved in checking this, so let's see how people
999 react first. */
1000 if (subnet && !subnet -> group -> authoritative) {
1001 static int eso = 0;
1002 log_info ("%s: not authoritative for subnet %s",
1003 msgbuf, piaddr (subnet -> net));
1004 if (!eso) {
1005 log_info ("If this DHCP server is authoritative for%s",
1006 " that subnet,");
1007 log_info ("please write an `authoritative;' directi%s",
1008 "ve either in the");
1009 log_info ("subnet declaration or in some scope that%s",
1010 " encloses the");
1011 log_info ("subnet declaration - for example, write %s",
1012 "it at the top");
1013 log_info ("of the dhcpd.conf file.");
1015 if (eso++ == 100)
1016 eso = 0;
1017 subnet_dereference (&subnet, MDL);
1018 return;
1021 memset (&d1, 0, sizeof d1);
1022 option_state_allocate (&options, MDL);
1023 memset (&outgoing, 0, sizeof outgoing);
1024 memset (&raw, 0, sizeof raw);
1025 outgoing.raw = &raw;
1027 /* Execute statements in scope starting with the subnet scope. */
1028 if (subnet)
1029 execute_statements_in_scope ((struct binding_value **)0,
1030 packet, (struct lease *)0,
1031 (struct client_state *)0,
1032 packet -> options, options,
1033 &global_scope, subnet -> group,
1034 (struct group *)0);
1036 /* Execute statements in the class scopes. */
1037 for (i = packet -> class_count; i > 0; i--) {
1038 execute_statements_in_scope
1039 ((struct binding_value **)0, packet, (struct lease *)0,
1040 (struct client_state *)0, packet -> options, options,
1041 &global_scope, packet -> classes [i - 1] -> group,
1042 subnet ? subnet -> group : (struct group *)0);
1045 /* Figure out the filename. */
1046 memset (&d1, 0, sizeof d1);
1047 oc = lookup_option (&server_universe, options, SV_FILENAME);
1048 if (oc &&
1049 evaluate_option_cache (&d1, packet, (struct lease *)0,
1050 (struct client_state *)0,
1051 packet -> options, (struct option_state *)0,
1052 &global_scope, oc, MDL)) {
1053 i = d1.len;
1054 if (i > sizeof raw.file)
1055 i = sizeof raw.file;
1056 else
1057 raw.file [i] = 0;
1058 memcpy (raw.file, d1.data, i);
1059 data_string_forget (&d1, MDL);
1062 /* Choose a server name as above. */
1063 oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
1064 if (oc &&
1065 evaluate_option_cache (&d1, packet, (struct lease *)0,
1066 (struct client_state *)0,
1067 packet -> options, (struct option_state *)0,
1068 &global_scope, oc, MDL)) {
1069 i = d1.len;
1070 if (i > sizeof raw.sname)
1071 i = sizeof raw.sname;
1072 else
1073 raw.sname [i] = 0;
1074 memcpy (raw.sname, d1.data, i);
1075 data_string_forget (&d1, MDL);
1078 /* Set a flag if this client is a lame Microsoft client that NUL
1079 terminates string options and expects us to do likewise. */
1080 nulltp = 0;
1081 if ((oc = lookup_option (&dhcp_universe, packet -> options,
1082 DHO_HOST_NAME))) {
1083 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
1084 (struct client_state *)0,
1085 packet -> options, options,
1086 &global_scope, oc, MDL)) {
1087 if (d1.data [d1.len - 1] == '\0')
1088 nulltp = 1;
1089 data_string_forget (&d1, MDL);
1093 /* Put in DHCP-specific options. */
1094 i = DHO_DHCP_MESSAGE_TYPE;
1095 oc = (struct option_cache *)0;
1096 if (option_cache_allocate (&oc, MDL)) {
1097 if (make_const_data (&oc -> expression,
1098 &dhcpack, 1, 0, 0, MDL)) {
1099 oc -> option = dhcp_universe.options [i];
1100 save_option (&dhcp_universe, options, oc);
1102 option_cache_dereference (&oc, MDL);
1105 i = DHO_DHCP_SERVER_IDENTIFIER;
1106 if (!(oc = lookup_option (&dhcp_universe, options, i))) {
1107 use_primary:
1108 oc = (struct option_cache *)0;
1109 if (option_cache_allocate (&oc, MDL)) {
1110 if (make_const_data
1111 (&oc -> expression,
1112 ((unsigned char *)
1113 &packet -> interface -> primary_address),
1114 sizeof packet -> interface -> primary_address,
1115 0, 0, MDL)) {
1116 oc -> option =
1117 dhcp_universe.options [i];
1118 save_option (&dhcp_universe,
1119 options, oc);
1121 option_cache_dereference (&oc, MDL);
1123 from = packet -> interface -> primary_address;
1124 } else {
1125 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
1126 (struct client_state *)0,
1127 packet -> options, options,
1128 &global_scope, oc, MDL)) {
1129 if (!d1.len || d1.len != sizeof from) {
1130 data_string_forget (&d1, MDL);
1131 goto use_primary;
1133 memcpy (&from, d1.data, sizeof from);
1134 data_string_forget (&d1, MDL);
1135 } else
1136 goto use_primary;
1139 /* Use the subnet mask from the subnet declaration if no other
1140 mask has been provided. */
1141 i = DHO_SUBNET_MASK;
1142 if (subnet && !lookup_option (&dhcp_universe, options, i)) {
1143 oc = (struct option_cache *)0;
1144 if (option_cache_allocate (&oc, MDL)) {
1145 if (make_const_data (&oc -> expression,
1146 subnet -> netmask.iabuf,
1147 subnet -> netmask.len,
1148 0, 0, MDL)) {
1149 oc -> option = dhcp_universe.options [i];
1150 save_option (&dhcp_universe, options, oc);
1152 option_cache_dereference (&oc, MDL);
1156 /* If a site option space has been specified, use that for
1157 site option codes. */
1158 i = SV_SITE_OPTION_SPACE;
1159 if ((oc = lookup_option (&server_universe, options, i)) &&
1160 evaluate_option_cache (&d1, packet, (struct lease *)0,
1161 (struct client_state *)0,
1162 packet -> options, options,
1163 &global_scope, oc, MDL)) {
1164 struct universe *u = (struct universe *)0;
1166 if (!universe_hash_lookup (&u, universe_hash,
1167 (const char *)d1.data, d1.len,
1168 MDL)) {
1169 log_error ("unknown option space %s.", d1.data);
1170 option_state_dereference (&options, MDL);
1171 if (subnet)
1172 subnet_dereference (&subnet, MDL);
1173 return;
1176 options -> site_universe = u -> index;
1177 options -> site_code_min = 128; /* XXX */
1178 data_string_forget (&d1, MDL);
1179 } else {
1180 options -> site_universe = dhcp_universe.index;
1181 options -> site_code_min = 0; /* Trust me, it works. */
1184 memset (&prl, 0, sizeof prl);
1186 /* Use the parameter list from the scope if there is one. */
1187 oc = lookup_option (&dhcp_universe, options,
1188 DHO_DHCP_PARAMETER_REQUEST_LIST);
1190 /* Otherwise, if the client has provided a list of options
1191 that it wishes returned, use it to prioritize. Otherwise,
1192 prioritize based on the default priority list. */
1194 if (!oc)
1195 oc = lookup_option (&dhcp_universe, packet -> options,
1196 DHO_DHCP_PARAMETER_REQUEST_LIST);
1198 if (oc)
1199 evaluate_option_cache (&prl, packet, (struct lease *)0,
1200 (struct client_state *)0,
1201 packet -> options, options,
1202 &global_scope, oc, MDL);
1204 #ifdef DEBUG_PACKET
1205 dump_packet (packet);
1206 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
1207 #endif
1209 log_info ("%s", msgbuf);
1211 /* Figure out the address of the boot file server. */
1212 raw.siaddr = from;
1213 if ((oc =
1214 lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
1215 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
1216 (struct client_state *)0,
1217 packet -> options, options,
1218 &global_scope, oc, MDL)) {
1219 /* If there was more than one answer,
1220 take the first. */
1221 if (d1.len >= 4 && d1.data)
1222 memcpy (&raw.siaddr, d1.data, 4);
1223 data_string_forget (&d1, MDL);
1227 /* Set up the option buffer... */
1228 outgoing.packet_length =
1229 cons_options (packet, outgoing.raw, (struct lease *)0,
1230 (struct client_state *)0,
1231 0, packet -> options, options, &global_scope,
1232 0, nulltp, 0,
1233 prl.len ? &prl : (struct data_string *)0,
1234 (char *)0);
1235 option_state_dereference (&options, MDL);
1236 data_string_forget (&prl, MDL);
1238 /* Make sure that the packet is at least as big as a BOOTP packet. */
1239 if (outgoing.packet_length < BOOTP_MIN_LEN)
1240 outgoing.packet_length = BOOTP_MIN_LEN;
1242 raw.giaddr = packet -> raw -> giaddr;
1243 raw.ciaddr = packet -> raw -> ciaddr;
1244 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
1245 raw.hlen = packet -> raw -> hlen;
1246 raw.htype = packet -> raw -> htype;
1248 raw.xid = packet -> raw -> xid;
1249 raw.secs = packet -> raw -> secs;
1250 raw.flags = packet -> raw -> flags;
1251 raw.hops = packet -> raw -> hops;
1252 raw.op = BOOTREPLY;
1254 /* Report what we're sending... */
1255 log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));
1257 #ifdef DEBUG_PACKET
1258 dump_packet (&outgoing);
1259 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
1260 #endif
1262 /* Set up the common stuff... */
1263 to.sin_family = AF_INET;
1264 #ifdef HAVE_SA_LEN
1265 to.sin_len = sizeof to;
1266 #endif
1267 memset (to.sin_zero, 0, sizeof to.sin_zero);
1269 /* Use the IP address we derived for the client. */
1270 memcpy (&to.sin_addr, cip.iabuf, 4);
1271 to.sin_port = remote_port;
1273 errno = 0;
1274 send_packet ((fallback_interface
1275 ? fallback_interface : packet -> interface),
1276 &outgoing, &raw, outgoing.packet_length,
1277 from, &to, (struct hardware *)0);
1278 if (subnet)
1279 subnet_dereference (&subnet, MDL);
1282 void nak_lease (packet, cip)
1283 struct packet *packet;
1284 struct iaddr *cip;
1286 struct sockaddr_in to;
1287 struct in_addr from;
1288 int result;
1289 struct dhcp_packet raw;
1290 unsigned char nak = DHCPNAK;
1291 struct packet outgoing;
1292 struct hardware hto;
1293 unsigned i;
1294 struct data_string data;
1295 struct option_state *options = (struct option_state *)0;
1296 struct expression *expr;
1297 struct option_cache *oc = (struct option_cache *)0;
1298 struct iaddr myfrom;
1300 option_state_allocate (&options, MDL);
1301 memset (&outgoing, 0, sizeof outgoing);
1302 memset (&raw, 0, sizeof raw);
1303 outgoing.raw = &raw;
1305 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
1306 if (!option_cache_allocate (&oc, MDL)) {
1307 log_error ("No memory for DHCPNAK message type.");
1308 option_state_dereference (&options, MDL);
1309 return;
1311 if (!make_const_data (&oc -> expression, &nak, sizeof nak,
1312 0, 0, MDL)) {
1313 log_error ("No memory for expr_const expression.");
1314 option_cache_dereference (&oc, MDL);
1315 option_state_dereference (&options, MDL);
1316 return;
1318 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];
1319 save_option (&dhcp_universe, options, oc);
1320 option_cache_dereference (&oc, MDL);
1322 /* Set DHCP_MESSAGE to whatever the message is */
1323 if (!option_cache_allocate (&oc, MDL)) {
1324 log_error ("No memory for DHCPNAK message type.");
1325 option_state_dereference (&options, MDL);
1326 return;
1328 if (!make_const_data (&oc -> expression,
1329 (unsigned char *)dhcp_message,
1330 strlen (dhcp_message), 1, 0, MDL)) {
1331 log_error ("No memory for expr_const expression.");
1332 option_cache_dereference (&oc, MDL);
1333 option_state_dereference (&options, MDL);
1334 return;
1336 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];
1337 save_option (&dhcp_universe, options, oc);
1338 option_cache_dereference (&oc, MDL);
1340 i = DHO_DHCP_SERVER_IDENTIFIER;
1341 if (!(oc = lookup_option (&dhcp_universe, options, i))) {
1342 use_primary:
1343 oc = (struct option_cache *)0;
1344 if (option_cache_allocate (&oc, MDL)) {
1345 if (make_const_data
1346 (&oc -> expression,
1347 ((unsigned char *)
1348 &packet -> interface -> primary_address),
1349 sizeof packet -> interface -> primary_address,
1350 0, 0, MDL)) {
1351 oc -> option =
1352 dhcp_universe.options [i];
1353 save_option (&dhcp_universe, options, oc);
1355 option_cache_dereference (&oc, MDL);
1357 myfrom.len = sizeof packet -> interface -> primary_address;
1358 memcpy (myfrom.iabuf,
1359 &packet -> interface -> primary_address, myfrom.len);
1360 } else {
1361 memset (&data, 0, sizeof data);
1362 if (evaluate_option_cache (&data, packet, (struct lease *)0,
1363 (struct client_state *)0,
1364 packet -> options, options,
1365 &global_scope, oc, MDL)) {
1366 if (!data.len ||
1367 data.len > sizeof myfrom.iabuf) {
1368 data_string_forget (&data, MDL);
1369 goto use_primary;
1371 memcpy (myfrom.iabuf, data.data, data.len);
1372 myfrom.len = data.len;
1373 data_string_forget (&data, MDL);
1374 } else
1375 goto use_primary;
1378 /* If there were agent options in the incoming packet, return
1379 them. */
1380 if (packet -> raw -> giaddr.s_addr &&
1381 packet -> options -> universe_count > agent_universe.index &&
1382 packet -> options -> universes [agent_universe.index]) {
1383 option_chain_head_reference
1384 ((struct option_chain_head **)
1385 &(options -> universes [agent_universe.index]),
1386 (struct option_chain_head *)
1387 packet -> options -> universes [agent_universe.index],
1388 MDL);
1391 /* Do not use the client's requested parameter list. */
1392 delete_option (&dhcp_universe, packet -> options,
1393 DHO_DHCP_PARAMETER_REQUEST_LIST);
1395 /* Set up the option buffer... */
1396 outgoing.packet_length =
1397 cons_options (packet, outgoing.raw, (struct lease *)0,
1398 (struct client_state *)0,
1399 0, packet -> options, options, &global_scope,
1400 0, 0, 0, (struct data_string *)0, (char *)0);
1401 option_state_dereference (&options, MDL);
1403 /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
1404 raw.siaddr = packet -> interface -> primary_address;
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;
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;
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);
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
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
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);
1449 memcpy (&from, myfrom.iabuf, sizeof from);
1451 /* Make sure that the packet is at least as big as a BOOTP packet. */
1452 if (outgoing.packet_length < BOOTP_MIN_LEN)
1453 outgoing.packet_length = BOOTP_MIN_LEN;
1455 /* If this was gatewayed, send it back to the gateway.
1456 Otherwise, broadcast it on the local network. */
1457 if (raw.giaddr.s_addr) {
1458 to.sin_addr = raw.giaddr;
1459 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
1460 to.sin_port = local_port;
1461 else
1462 to.sin_port = remote_port; /* for testing. */
1464 if (fallback_interface) {
1465 result = send_packet (fallback_interface,
1466 packet, &raw,
1467 outgoing.packet_length,
1468 from, &to, &hto);
1469 return;
1471 } else {
1472 to.sin_addr = limited_broadcast;
1473 to.sin_port = remote_port;
1476 errno = 0;
1477 result = send_packet (packet -> interface,
1478 packet, &raw, outgoing.packet_length,
1479 from, &to, (struct hardware *)0);
1482 void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
1483 struct packet *packet;
1484 struct lease *lease;
1485 unsigned int offer;
1486 TIME when;
1487 char *msg;
1488 int ms_nulltp;
1490 struct lease *lt;
1491 struct lease_state *state;
1492 struct lease *next;
1493 struct host_decl *host = (struct host_decl *)0;
1494 TIME lease_time;
1495 TIME offered_lease_time;
1496 struct data_string d1;
1497 TIME min_lease_time;
1498 TIME max_lease_time;
1499 TIME default_lease_time;
1500 struct option_cache *oc;
1501 struct expression *expr;
1502 int status;
1503 isc_result_t result;
1504 int did_ping = 0;
1505 TIME ping_timeout;
1507 unsigned i, j;
1508 int s1, s2;
1509 int val;
1510 int ignorep;
1512 /* If we're already acking this lease, don't do it again. */
1513 if (lease -> state)
1514 return;
1516 /* If the lease carries a host record, remember it. */
1517 if (lease -> host)
1518 host_reference (&host, lease -> host, MDL);
1520 /* Allocate a lease state structure... */
1521 state = new_lease_state (MDL);
1522 if (!state)
1523 log_fatal ("unable to allocate lease state!");
1524 state -> got_requested_address = packet -> got_requested_address;
1525 shared_network_reference (&state -> shared_network,
1526 packet -> interface -> shared_network, MDL);
1528 /* See if we got a server identifier option. */
1529 if (lookup_option (&dhcp_universe,
1530 packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
1531 state -> got_server_identifier = 1;
1533 /* If there were agent options in the incoming packet, return
1534 them. Do not return the agent options if they were stashed
1535 on the lease. */
1536 if (packet -> raw -> giaddr.s_addr &&
1537 packet -> options -> universe_count > agent_universe.index &&
1538 packet -> options -> universes [agent_universe.index] &&
1539 (state -> options -> universe_count <= agent_universe.index ||
1540 !state -> options -> universes [agent_universe.index]) &&
1541 lease -> agent_options !=
1542 ((struct option_chain_head *)
1543 packet -> options -> universes [agent_universe.index])) {
1544 option_chain_head_reference
1545 ((struct option_chain_head **)
1546 &(state -> options -> universes [agent_universe.index]),
1547 (struct option_chain_head *)
1548 packet -> options -> universes [agent_universe.index],
1549 MDL);
1552 /* If we are offering a lease that is still currently valid, preserve
1553 the events. We need to do this because if the client does not
1554 REQUEST our offer, it will expire in 2 minutes, overriding the
1555 expire time in the currently in force lease. We want the expire
1556 events to be executed at that point. */
1557 if (lease -> ends <= cur_time && offer != DHCPOFFER) {
1558 /* Get rid of any old expiry or release statements - by
1559 executing the statements below, we will be inserting new
1560 ones if there are any to insert. */
1561 if (lease -> on_expiry)
1562 executable_statement_dereference (&lease -> on_expiry,
1563 MDL);
1564 if (lease -> on_commit)
1565 executable_statement_dereference (&lease -> on_commit,
1566 MDL);
1567 if (lease -> on_release)
1568 executable_statement_dereference (&lease -> on_release,
1569 MDL);
1572 /* Execute statements in scope starting with the subnet scope. */
1573 execute_statements_in_scope ((struct binding_value **)0,
1574 packet, lease, (struct client_state *)0,
1575 packet -> options,
1576 state -> options, &lease -> scope,
1577 lease -> subnet -> group,
1578 (struct group *)0);
1580 /* If the lease is from a pool, run the pool scope. */
1581 if (lease -> pool)
1582 (execute_statements_in_scope
1583 ((struct binding_value **)0, packet, lease,
1584 (struct client_state *)0, packet -> options,
1585 state -> options, &lease -> scope, lease -> pool -> group,
1586 lease -> pool -> shared_network -> group));
1588 /* Execute statements from class scopes. */
1589 for (i = packet -> class_count; i > 0; i--) {
1590 execute_statements_in_scope
1591 ((struct binding_value **)0,
1592 packet, lease, (struct client_state *)0,
1593 packet -> options, state -> options,
1594 &lease -> scope, packet -> classes [i - 1] -> group,
1595 (lease -> pool
1596 ? lease -> pool -> group
1597 : lease -> subnet -> group));
1600 /* See if the client is only supposed to have one lease at a time,
1601 and if so, find its other leases and release them. We can only
1602 do this on DHCPREQUEST. It's a little weird to do this before
1603 looking at permissions, because the client might not actually
1604 _get_ a lease after we've done the permission check, but the
1605 assumption for this option is that the client has exactly one
1606 network interface, and will only ever remember one lease. So
1607 if it sends a DHCPREQUEST, and doesn't get the lease, it's already
1608 forgotten about its old lease, so we can too. */
1609 if (packet -> packet_type == DHCPREQUEST &&
1610 (oc = lookup_option (&server_universe, state -> options,
1611 SV_ONE_LEASE_PER_CLIENT)) &&
1612 evaluate_boolean_option_cache (&ignorep,
1613 packet, lease,
1614 (struct client_state *)0,
1615 packet -> options,
1616 state -> options, &lease -> scope,
1617 oc, MDL)) {
1618 struct lease *seek;
1619 if (lease -> uid_len) {
1620 do {
1621 seek = (struct lease *)0;
1622 find_lease_by_uid (&seek, lease -> uid,
1623 lease -> uid_len, MDL);
1624 if (!seek)
1625 break;
1626 if (seek == lease && !seek -> n_uid) {
1627 lease_dereference (&seek, MDL);
1628 break;
1630 next = (struct lease *)0;
1632 /* Don't release expired leases, and don't
1633 release the lease we're going to assign. */
1634 next = (struct lease *)0;
1635 while (seek) {
1636 if (seek -> n_uid)
1637 lease_reference (&next, seek -> n_uid, MDL);
1638 if (seek != lease &&
1639 seek -> binding_state != FTS_RELEASED &&
1640 seek -> binding_state != FTS_EXPIRED &&
1641 seek -> binding_state != FTS_RESET &&
1642 seek -> binding_state != FTS_FREE &&
1643 seek -> binding_state != FTS_BACKUP)
1644 break;
1645 lease_dereference (&seek, MDL);
1646 if (next) {
1647 lease_reference (&seek, next, MDL);
1648 lease_dereference (&next, MDL);
1651 if (next)
1652 lease_dereference (&next, MDL);
1653 if (seek) {
1654 release_lease (seek, packet);
1655 lease_dereference (&seek, MDL);
1656 } else
1657 break;
1658 } while (1);
1660 if (!lease -> uid_len ||
1661 (host &&
1662 !host -> client_identifier.len &&
1663 (oc = lookup_option (&server_universe, state -> options,
1664 SV_DUPLICATES)) &&
1665 !evaluate_boolean_option_cache (&ignorep, packet, lease,
1666 (struct client_state *)0,
1667 packet -> options,
1668 state -> options,
1669 &lease -> scope,
1670 oc, MDL))) {
1671 do {
1672 seek = (struct lease *)0;
1673 find_lease_by_hw_addr
1674 (&seek, lease -> hardware_addr.hbuf,
1675 lease -> hardware_addr.hlen, MDL);
1676 if (!seek)
1677 break;
1678 if (seek == lease && !seek -> n_hw) {
1679 lease_dereference (&seek, MDL);
1680 break;
1682 next = (struct lease *)0;
1683 while (seek) {
1684 if (seek -> n_hw)
1685 lease_reference (&next, seek -> n_hw, MDL);
1686 if (seek != lease &&
1687 seek -> binding_state != FTS_RELEASED &&
1688 seek -> binding_state != FTS_EXPIRED &&
1689 seek -> binding_state != FTS_RESET &&
1690 seek -> binding_state != FTS_FREE &&
1691 seek -> binding_state != FTS_BACKUP)
1692 break;
1693 lease_dereference (&seek, MDL);
1694 if (next) {
1695 lease_reference (&seek, next, MDL);
1696 lease_dereference (&next, MDL);
1699 if (next)
1700 lease_dereference (&next, MDL);
1701 if (seek) {
1702 release_lease (seek, packet);
1703 lease_dereference (&seek, MDL);
1704 } else
1705 break;
1706 } while (1);
1711 /* Make sure this packet satisfies the configured minimum
1712 number of seconds. */
1713 memset (&d1, 0, sizeof d1);
1714 if (offer == DHCPOFFER &&
1715 (oc = lookup_option (&server_universe, state -> options,
1716 SV_MIN_SECS))) {
1717 if (evaluate_option_cache (&d1, packet, lease,
1718 (struct client_state *)0,
1719 packet -> options, state -> options,
1720 &lease -> scope, oc, MDL)) {
1721 if (d1.len &&
1722 ntohs (packet -> raw -> secs) < d1.data [0]) {
1723 log_info ("%s: %d secs < %d", msg,
1724 ntohs (packet -> raw -> secs),
1725 d1.data [0]);
1726 data_string_forget (&d1, MDL);
1727 free_lease_state (state, MDL);
1728 if (host)
1729 host_dereference (&host, MDL);
1730 return;
1732 data_string_forget (&d1, MDL);
1736 /* Try to find a matching host declaration for this lease.
1738 if (!host) {
1739 struct host_decl *hp = (struct host_decl *)0;
1740 struct host_decl *h;
1742 /* Try to find a host_decl that matches the client
1743 identifier or hardware address on the packet, and
1744 has no fixed IP address. If there is one, hang
1745 it off the lease so that its option definitions
1746 can be used. */
1747 oc = lookup_option (&dhcp_universe, packet -> options,
1748 DHO_DHCP_CLIENT_IDENTIFIER);
1749 if (oc &&
1750 evaluate_option_cache (&d1, packet, lease,
1751 (struct client_state *)0,
1752 packet -> options, state -> options,
1753 &lease -> scope, oc, MDL)) {
1754 find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
1755 data_string_forget (&d1, MDL);
1756 if (hp)
1757 host_reference (&host, hp, MDL);
1759 if (!hp) {
1760 find_hosts_by_haddr (&hp,
1761 packet -> raw -> htype,
1762 packet -> raw -> chaddr,
1763 packet -> raw -> hlen,
1764 MDL);
1765 for (h = hp; h; h = h -> n_ipaddr) {
1766 if (!h -> fixed_addr)
1767 break;
1769 if (h)
1770 host_reference (&host, h, MDL);
1772 if (hp)
1773 host_dereference (&hp, MDL);
1776 /* If we have a host_decl structure, run the options associated
1777 with its group. Wether the host decl struct is old or not. */
1778 if (host)
1779 execute_statements_in_scope ((struct binding_value **)0,
1780 packet, lease,
1781 (struct client_state *)0,
1782 packet -> options,
1783 state -> options, &lease -> scope,
1784 host -> group,
1785 (lease -> pool
1786 ? lease -> pool -> group
1787 : lease -> subnet -> group));
1789 /* Drop the request if it's not allowed for this client. By
1790 default, unknown clients are allowed. */
1791 if (!host &&
1792 (oc = lookup_option (&server_universe, state -> options,
1793 SV_BOOT_UNKNOWN_CLIENTS)) &&
1794 !evaluate_boolean_option_cache (&ignorep,
1795 packet, lease,
1796 (struct client_state *)0,
1797 packet -> options,
1798 state -> options,
1799 &lease -> scope, oc, MDL)) {
1800 if (!ignorep)
1801 log_info ("%s: unknown client", msg);
1802 free_lease_state (state, MDL);
1803 if (host)
1804 host_dereference (&host, MDL);
1805 return;
1808 /* Drop the request if it's not allowed for this client. */
1809 if (!offer &&
1810 (oc = lookup_option (&server_universe, state -> options,
1811 SV_ALLOW_BOOTP)) &&
1812 !evaluate_boolean_option_cache (&ignorep,
1813 packet, lease,
1814 (struct client_state *)0,
1815 packet -> options,
1816 state -> options,
1817 &lease -> scope, oc, MDL)) {
1818 if (!ignorep)
1819 log_info ("%s: bootp disallowed", msg);
1820 free_lease_state (state, MDL);
1821 if (host)
1822 host_dereference (&host, MDL);
1823 return;
1826 /* Drop the request if booting is specifically denied. */
1827 oc = lookup_option (&server_universe, state -> options,
1828 SV_ALLOW_BOOTING);
1829 if (oc &&
1830 !evaluate_boolean_option_cache (&ignorep,
1831 packet, lease,
1832 (struct client_state *)0,
1833 packet -> options,
1834 state -> options,
1835 &lease -> scope, oc, MDL)) {
1836 if (!ignorep)
1837 log_info ("%s: booting disallowed", msg);
1838 free_lease_state (state, MDL);
1839 if (host)
1840 host_dereference (&host, MDL);
1841 return;
1844 /* If we are configured to do per-class billing, do it. */
1845 if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
1846 /* See if the lease is currently being billed to a
1847 class, and if so, whether or not it can continue to
1848 be billed to that class. */
1849 if (lease -> billing_class) {
1850 for (i = 0; i < packet -> class_count; i++)
1851 if (packet -> classes [i] ==
1852 lease -> billing_class)
1853 break;
1854 if (i == packet -> class_count)
1855 unbill_class (lease, lease -> billing_class);
1858 /* If we don't have an active billing, see if we need
1859 one, and if we do, try to do so. */
1860 if (!lease -> billing_class) {
1861 for (i = 0; i < packet -> class_count; i++) {
1862 if (packet -> classes [i] -> lease_limit)
1863 break;
1865 if (i != packet -> class_count) {
1866 for (i = 0; i < packet -> class_count; i++)
1867 if ((packet ->
1868 classes [i] -> lease_limit) &&
1869 bill_class (lease,
1870 packet -> classes [i]))
1871 break;
1872 if (i == packet -> class_count) {
1873 log_info ("%s: no available billing",
1874 msg);
1875 free_lease_state (state, MDL);
1876 if (host)
1877 host_dereference (&host, MDL);
1878 /* XXX possibly not necessary: */
1879 return;
1885 /* Figure out the filename. */
1886 oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
1887 if (oc)
1888 evaluate_option_cache (&state -> filename, packet, lease,
1889 (struct client_state *)0,
1890 packet -> options, state -> options,
1891 &lease -> scope, oc, MDL);
1893 /* Choose a server name as above. */
1894 oc = lookup_option (&server_universe, state -> options,
1895 SV_SERVER_NAME);
1896 if (oc)
1897 evaluate_option_cache (&state -> server_name, packet, lease,
1898 (struct client_state *)0,
1899 packet -> options, state -> options,
1900 &lease -> scope, oc, MDL);
1902 /* At this point, we have a lease that we can offer the client.
1903 Now we construct a lease structure that contains what we want,
1904 and call supersede_lease to do the right thing with it. */
1905 lt = (struct lease *)0;
1906 result = lease_allocate (&lt, MDL);
1907 if (result != ISC_R_SUCCESS) {
1908 log_info ("%s: can't allocate temporary lease structure: %s",
1909 msg, isc_result_totext (result));
1910 free_lease_state (state, MDL);
1911 if (host)
1912 host_dereference (&host, MDL);
1913 return;
1916 /* Use the ip address of the lease that we finally found in
1917 the database. */
1918 lt -> ip_addr = lease -> ip_addr;
1920 /* Start now. */
1921 lt -> starts = cur_time;
1923 /* Figure out how long a lease to assign. If this is a
1924 dynamic BOOTP lease, its duration must be infinite. */
1925 if (offer) {
1926 default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
1927 if ((oc = lookup_option (&server_universe, state -> options,
1928 SV_DEFAULT_LEASE_TIME))) {
1929 if (evaluate_option_cache (&d1, packet, lease,
1930 (struct client_state *)0,
1931 packet -> options,
1932 state -> options,
1933 &lease -> scope, oc, MDL)) {
1934 if (d1.len == sizeof (u_int32_t))
1935 default_lease_time =
1936 getULong (d1.data);
1937 data_string_forget (&d1, MDL);
1941 if ((oc = lookup_option (&dhcp_universe, packet -> options,
1942 DHO_DHCP_LEASE_TIME)))
1943 s1 = evaluate_option_cache (&d1, packet, lease,
1944 (struct client_state *)0,
1945 packet -> options,
1946 state -> options,
1947 &lease -> scope, oc, MDL);
1948 else
1949 s1 = 0;
1951 if (s1 && d1.len == sizeof (u_int32_t)) {
1952 lease_time = getULong (d1.data);
1953 data_string_forget (&d1, MDL);
1954 } else {
1955 if (s1)
1956 data_string_forget (&d1, MDL);
1957 lease_time = default_lease_time;
1960 /* See if there's a maximum lease time. */
1961 max_lease_time = DEFAULT_MAX_LEASE_TIME;
1962 if ((oc = lookup_option (&server_universe, state -> options,
1963 SV_MAX_LEASE_TIME))) {
1964 if (evaluate_option_cache (&d1, packet, lease,
1965 (struct client_state *)0,
1966 packet -> options,
1967 state -> options,
1968 &lease -> scope, oc, MDL)) {
1969 if (d1.len == sizeof (u_int32_t))
1970 max_lease_time =
1971 getULong (d1.data);
1972 data_string_forget (&d1, MDL);
1976 /* Enforce the maximum lease length. */
1977 if (lease_time < 0 /* XXX */
1978 || lease_time > max_lease_time)
1979 lease_time = max_lease_time;
1981 min_lease_time = DEFAULT_MIN_LEASE_TIME;
1982 if (min_lease_time > max_lease_time)
1983 min_lease_time = max_lease_time;
1985 if ((oc = lookup_option (&server_universe, state -> options,
1986 SV_MIN_LEASE_TIME))) {
1987 if (evaluate_option_cache (&d1, packet, lease,
1988 (struct client_state *)0,
1989 packet -> options,
1990 state -> options,
1991 &lease -> scope, oc, MDL)) {
1992 if (d1.len == sizeof (u_int32_t))
1993 min_lease_time = getULong (d1.data);
1994 data_string_forget (&d1, MDL);
1998 if (lease_time < min_lease_time) {
1999 if (min_lease_time)
2000 lease_time = min_lease_time;
2001 else
2002 lease_time = default_lease_time;
2005 #if defined (FAILOVER_PROTOCOL)
2006 /* Okay, we know the lease duration. Now check the
2007 failover state, if any. */
2008 if (lease -> tsfp) {
2009 lt ->tsfp = lease ->tsfp;
2011 if (lease -> pool && lease -> pool -> failover_peer) {
2012 dhcp_failover_state_t *peer =
2013 lease -> pool -> failover_peer;
2015 /* If the lease time we arrived at exceeds what
2016 the peer has, we can only issue a lease of
2017 peer -> mclt, but we can tell the peer we
2018 want something longer in the future. */
2019 /* XXX This may result in updates that only push
2020 XXX the peer's expiry time for this lease up
2021 XXX by a few seconds - think about this again
2022 XXX later. */
2023 if (lease_time > peer -> mclt &&
2024 cur_time + lease_time > lease -> tsfp) {
2025 /* Here we're assuming that if we don't have
2026 to update tstp, there's already an update
2027 queued. May want to revisit this. */
2028 if (peer -> me.state != partner_down &&
2029 cur_time + lease_time > lease -> tstp)
2030 lt -> tstp = (cur_time + lease_time +
2031 peer -> mclt / 2);
2033 /* Now choose a lease time that is either
2034 MCLT, for a lease that's never before been
2035 assigned, or TSFP + MCLT for a lease that
2036 has.
2037 XXX Note that TSFP may be < cur_time.
2038 XXX What do we do in this case?
2039 XXX should the expiry timer on the lease
2040 XXX set tsfp and tstp to zero? */
2041 if (lease -> tsfp < cur_time) {
2042 lease_time = peer -> mclt;
2043 } else {
2044 lease_time = (lease -> tsfp - cur_time
2045 + peer -> mclt);
2047 } else {
2048 if (cur_time + lease_time > lease -> tsfp &&
2049 lease_time > peer -> mclt / 2) {
2050 lt -> tstp = (cur_time + lease_time +
2051 peer -> mclt / 2);
2052 } else {
2053 lt -> tstp = (cur_time + lease_time +
2054 lease_time / 2);
2058 lt -> cltt = cur_time;
2060 #endif /* FAILOVER_PROTOCOL */
2062 /* If the lease duration causes the time value to wrap,
2063 use the maximum expiry time. */
2064 if (cur_time + lease_time < cur_time)
2065 state -> offered_expiry = MAX_TIME - 1;
2066 else
2067 state -> offered_expiry = cur_time + lease_time;
2068 if (when)
2069 lt -> ends = when;
2070 else
2071 lt -> ends = state -> offered_expiry;
2073 /* Don't make lease active until we actually get a
2074 DHCPREQUEST. */
2075 if (offer == DHCPACK)
2076 lt -> next_binding_state = FTS_ACTIVE;
2077 else
2078 lt -> next_binding_state = lease -> binding_state;
2079 } else {
2080 lease_time = MAX_TIME - cur_time;
2082 if ((oc = lookup_option (&server_universe, state -> options,
2083 SV_BOOTP_LEASE_LENGTH))) {
2084 if (evaluate_option_cache (&d1, packet, lease,
2085 (struct client_state *)0,
2086 packet -> options,
2087 state -> options,
2088 &lease -> scope, oc, MDL)) {
2089 if (d1.len == sizeof (u_int32_t))
2090 lease_time = getULong (d1.data);
2091 data_string_forget (&d1, MDL);
2095 if ((oc = lookup_option (&server_universe, state -> options,
2096 SV_BOOTP_LEASE_CUTOFF))) {
2097 if (evaluate_option_cache (&d1, packet, lease,
2098 (struct client_state *)0,
2099 packet -> options,
2100 state -> options,
2101 &lease -> scope, oc, MDL)) {
2102 if (d1.len == sizeof (u_int32_t))
2103 lease_time = (getULong (d1.data) -
2104 cur_time);
2105 data_string_forget (&d1, MDL);
2109 lt -> ends = state -> offered_expiry = cur_time + lease_time;
2110 lt -> next_binding_state = FTS_ACTIVE;
2113 lt -> timestamp = cur_time;
2115 /* Record the uid, if given... */
2116 oc = lookup_option (&dhcp_universe, packet -> options,
2117 DHO_DHCP_CLIENT_IDENTIFIER);
2118 if (oc &&
2119 evaluate_option_cache (&d1, packet, lease,
2120 (struct client_state *)0,
2121 packet -> options, state -> options,
2122 &lease -> scope, oc, MDL)) {
2123 if (d1.len <= sizeof lt -> uid_buf) {
2124 memcpy (lt -> uid_buf, d1.data, d1.len);
2125 lt -> uid = lt -> uid_buf;
2126 lt -> uid_max = sizeof lt -> uid_buf;
2127 lt -> uid_len = d1.len;
2128 } else {
2129 unsigned char *tuid;
2130 lt -> uid_max = d1.len;
2131 lt -> uid_len = d1.len;
2132 tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);
2133 /* XXX inelegant */
2134 if (!tuid)
2135 log_fatal ("no memory for large uid.");
2136 memcpy (tuid, d1.data, lt -> uid_len);
2137 lt -> uid = tuid;
2139 data_string_forget (&d1, MDL);
2142 if (host) {
2143 host_reference (&lt -> host, host, MDL);
2144 host_dereference (&host, MDL);
2146 if (lease -> subnet)
2147 subnet_reference (&lt -> subnet, lease -> subnet, MDL);
2148 if (lease -> billing_class)
2149 class_reference (&lt -> billing_class,
2150 lease -> billing_class, MDL);
2152 /* Set a flag if this client is a broken client that NUL
2153 terminates string options and expects us to do likewise. */
2154 if (ms_nulltp)
2155 lease -> flags |= MS_NULL_TERMINATION;
2156 else
2157 lease -> flags &= ~MS_NULL_TERMINATION;
2159 /* Save any bindings. */
2160 if (lease -> scope) {
2161 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
2162 binding_scope_dereference (&lease -> scope, MDL);
2164 if (lease -> agent_options)
2165 option_chain_head_reference (&lt -> agent_options,
2166 lease -> agent_options, MDL);
2168 /* If we got relay agent information options, and the packet really
2169 looks like it came through a relay agent, and if this feature is
2170 not disabled, save the relay agent information options that came
2171 in with the packet, so that we can use them at renewal time when
2172 the packet won't have gone through a relay agent. */
2173 if (packet -> raw -> giaddr.s_addr &&
2174 packet -> options -> universe_count > agent_universe.index &&
2175 packet -> options -> universes [agent_universe.index] &&
2176 (state -> options -> universe_count <= agent_universe.index ||
2177 state -> options -> universes [agent_universe.index] ==
2178 packet -> options -> universes [agent_universe.index])) {
2179 oc = lookup_option (&server_universe, state -> options,
2180 SV_STASH_AGENT_OPTIONS);
2181 if (!oc ||
2182 evaluate_boolean_option_cache (&ignorep, packet, lease,
2183 (struct client_state *)0,
2184 packet -> options,
2185 state -> options,
2186 &lease -> scope, oc, MDL)) {
2187 if (lt -> agent_options)
2188 option_chain_head_dereference (&lt -> agent_options, MDL);
2189 option_chain_head_reference
2190 (&lt -> agent_options,
2191 (struct option_chain_head *)
2192 packet -> options -> universes [agent_universe.index],
2193 MDL);
2197 /* Replace the old lease hostname with the new one, if it's changed. */
2198 oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
2199 if (oc)
2200 s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
2201 (struct client_state *)0,
2202 packet -> options,
2203 (struct option_state *)0,
2204 &global_scope, oc, MDL);
2205 else
2206 s1 = 0;
2208 if (oc && s1 &&
2209 lease -> client_hostname &&
2210 strlen (lease -> client_hostname) == d1.len &&
2211 !memcmp (lease -> client_hostname, d1.data, d1.len)) {
2212 /* Hasn't changed. */
2213 data_string_forget (&d1, MDL);
2214 lt -> client_hostname = lease -> client_hostname;
2215 lease -> client_hostname = (char *)0;
2216 } else if (oc && s1) {
2217 lt -> client_hostname = dmalloc (d1.len + 1, MDL);
2218 if (!lt -> client_hostname)
2219 log_error ("no memory for client hostname.");
2220 else {
2221 memcpy (lt -> client_hostname, d1.data, d1.len);
2222 lt -> client_hostname [d1.len] = 0;
2224 data_string_forget (&d1, MDL);
2227 /* Record the hardware address, if given... */
2228 lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
2229 lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
2230 memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
2231 sizeof packet -> raw -> chaddr);
2233 lt -> flags = lease -> flags & ~PERSISTENT_FLAGS;
2235 /* If there are statements to execute when the lease is
2236 committed, execute them. */
2237 if (lease -> on_commit && (!offer || offer == DHCPACK)) {
2238 execute_statements ((struct binding_value **)0,
2239 packet, lt, (struct client_state *)0,
2240 packet -> options,
2241 state -> options, &lt -> scope,
2242 lease -> on_commit);
2243 if (lease -> on_commit)
2244 executable_statement_dereference (&lease -> on_commit,
2245 MDL);
2248 #ifdef NSUPDATE
2249 /* Perform DDNS updates, if configured to. */
2250 if ((!offer || offer == DHCPACK) &&
2251 (!(oc = lookup_option (&server_universe, state -> options,
2252 SV_DDNS_UPDATES)) ||
2253 evaluate_boolean_option_cache (&ignorep, packet, lt,
2254 (struct client_state *)0,
2255 packet -> options,
2256 state -> options,
2257 &lt -> scope, oc, MDL))) {
2258 ddns_updates (packet, lt, lease, state);
2260 #endif /* NSUPDATE */
2262 /* Don't call supersede_lease on a mocked-up lease. */
2263 if (lease -> flags & STATIC_LEASE) {
2264 /* Copy the hardware address into the static lease
2265 structure. */
2266 lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
2267 lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
2268 memcpy (&lease -> hardware_addr.hbuf [1],
2269 packet -> raw -> chaddr,
2270 sizeof packet -> raw -> chaddr); /* XXX */
2271 } else {
2272 /* Install the new information about this lease in the
2273 database. If this is a DHCPACK or a dynamic BOOTREPLY
2274 and we can't write the lease, don't ACK it (or BOOTREPLY
2275 it) either. */
2277 if (!supersede_lease (lease, lt, !offer || offer == DHCPACK,
2278 offer == DHCPACK, offer == DHCPACK)) {
2279 log_info ("%s: database update failed", msg);
2280 free_lease_state (state, MDL);
2281 lease_dereference (&lt, MDL);
2282 return;
2285 lease_dereference (&lt, MDL);
2287 /* Remember the interface on which the packet arrived. */
2288 state -> ip = packet -> interface;
2290 /* Remember the giaddr, xid, secs, flags and hops. */
2291 state -> giaddr = packet -> raw -> giaddr;
2292 state -> ciaddr = packet -> raw -> ciaddr;
2293 state -> xid = packet -> raw -> xid;
2294 state -> secs = packet -> raw -> secs;
2295 state -> bootp_flags = packet -> raw -> flags;
2296 state -> hops = packet -> raw -> hops;
2297 state -> offer = offer;
2299 /* If we're always supposed to broadcast to this client, set
2300 the broadcast bit in the bootp flags field. */
2301 if ((oc = lookup_option (&server_universe, state -> options,
2302 SV_ALWAYS_BROADCAST)) &&
2303 evaluate_boolean_option_cache (&ignorep, packet, lease,
2304 (struct client_state *)0,
2305 packet -> options, state -> options,
2306 &lease -> scope, oc, MDL))
2307 state -> bootp_flags |= htons (BOOTP_BROADCAST);
2309 /* Get the Maximum Message Size option from the packet, if one
2310 was sent. */
2311 oc = lookup_option (&dhcp_universe, packet -> options,
2312 DHO_DHCP_MAX_MESSAGE_SIZE);
2313 if (oc &&
2314 evaluate_option_cache (&d1, packet, lease,
2315 (struct client_state *)0,
2316 packet -> options, state -> options,
2317 &lease -> scope, oc, MDL)) {
2318 if (d1.len == sizeof (u_int16_t))
2319 state -> max_message_size = getUShort (d1.data);
2320 data_string_forget (&d1, MDL);
2321 } else {
2322 oc = lookup_option (&dhcp_universe, state -> options,
2323 DHO_DHCP_MAX_MESSAGE_SIZE);
2324 if (oc &&
2325 evaluate_option_cache (&d1, packet, lease,
2326 (struct client_state *)0,
2327 packet -> options, state -> options,
2328 &lease -> scope, oc, MDL)) {
2329 if (d1.len == sizeof (u_int16_t))
2330 state -> max_message_size =
2331 getUShort (d1.data);
2332 data_string_forget (&d1, MDL);
2336 /* Get the Subnet Selection option from the packet, if one
2337 was sent. */
2338 if ((oc = lookup_option (&dhcp_universe, packet -> options,
2339 DHO_SUBNET_SELECTION))) {
2341 /* Make a copy of the data. */
2342 struct option_cache *noc = (struct option_cache *)0;
2343 if (option_cache_allocate (&noc, MDL)) {
2344 if (oc -> data.len)
2345 data_string_copy (&noc -> data,
2346 &oc -> data, MDL);
2347 if (oc -> expression)
2348 expression_reference (&noc -> expression,
2349 oc -> expression, MDL);
2350 if (oc -> option)
2351 noc -> option = oc -> option;
2354 save_option (&dhcp_universe, state -> options, noc);
2355 option_cache_dereference (&noc, MDL);
2358 /* Now, if appropriate, put in DHCP-specific options that
2359 override those. */
2360 if (state -> offer) {
2361 i = DHO_DHCP_MESSAGE_TYPE;
2362 oc = (struct option_cache *)0;
2363 if (option_cache_allocate (&oc, MDL)) {
2364 if (make_const_data (&oc -> expression,
2365 &state -> offer, 1, 0, 0, MDL)) {
2366 oc -> option =
2367 dhcp_universe.options [i];
2368 save_option (&dhcp_universe,
2369 state -> options, oc);
2371 option_cache_dereference (&oc, MDL);
2373 i = DHO_DHCP_SERVER_IDENTIFIER;
2374 if (!(oc = lookup_option (&dhcp_universe,
2375 state -> options, i))) {
2376 use_primary:
2377 oc = (struct option_cache *)0;
2378 if (option_cache_allocate (&oc, MDL)) {
2379 if (make_const_data
2380 (&oc -> expression,
2381 ((unsigned char *)
2382 &state -> ip -> primary_address),
2383 sizeof state -> ip -> primary_address,
2384 0, 0, MDL)) {
2385 oc -> option =
2386 dhcp_universe.options [i];
2387 save_option (&dhcp_universe,
2388 state -> options, oc);
2390 option_cache_dereference (&oc, MDL);
2392 state -> from.len =
2393 sizeof state -> ip -> primary_address;
2394 memcpy (state -> from.iabuf,
2395 &state -> ip -> primary_address,
2396 state -> from.len);
2397 } else {
2398 if (evaluate_option_cache (&d1, packet, lease,
2399 (struct client_state *)0,
2400 packet -> options,
2401 state -> options,
2402 &lease -> scope, oc, MDL)) {
2403 if (!d1.len ||
2404 d1.len > sizeof state -> from.iabuf) {
2405 data_string_forget (&d1, MDL);
2406 goto use_primary;
2408 memcpy (state -> from.iabuf, d1.data, d1.len);
2409 state -> from.len = d1.len;
2410 data_string_forget (&d1, MDL);
2411 } else
2412 goto use_primary;
2415 offered_lease_time =
2416 state -> offered_expiry - cur_time;
2418 putULong ((unsigned char *)&state -> expiry,
2419 (unsigned long)offered_lease_time);
2420 i = DHO_DHCP_LEASE_TIME;
2421 if (lookup_option (&dhcp_universe, state -> options, i))
2422 log_error ("dhcp-lease-time option for %s overridden.",
2423 inet_ntoa (state -> ciaddr));
2424 oc = (struct option_cache *)0;
2425 if (option_cache_allocate (&oc, MDL)) {
2426 if (make_const_data (&oc -> expression,
2427 (unsigned char *)&state -> expiry,
2428 sizeof state -> expiry,
2429 0, 0, MDL)) {
2430 oc -> option = dhcp_universe.options [i];
2431 save_option (&dhcp_universe,
2432 state -> options, oc);
2434 option_cache_dereference (&oc, MDL);
2437 /* Renewal time is lease time * 0.5. */
2438 offered_lease_time /= 2;
2439 putULong ((unsigned char *)&state -> renewal,
2440 (unsigned long)offered_lease_time);
2441 i = DHO_DHCP_RENEWAL_TIME;
2442 if (lookup_option (&dhcp_universe, state -> options, i))
2443 log_error ("overriding dhcp-renewal-time for %s.",
2444 inet_ntoa (state -> ciaddr));
2445 oc = (struct option_cache *)0;
2446 if (option_cache_allocate (&oc, MDL)) {
2447 if (make_const_data (&oc -> expression,
2448 (unsigned char *)
2449 &state -> renewal,
2450 sizeof state -> renewal,
2451 0, 0, MDL)) {
2452 oc -> option = dhcp_universe.options [i];
2453 save_option (&dhcp_universe,
2454 state -> options, oc);
2456 option_cache_dereference (&oc, MDL);
2459 /* Rebinding time is lease time * 0.875. */
2460 offered_lease_time += (offered_lease_time / 2
2461 + offered_lease_time / 4);
2462 putULong ((unsigned char *)&state -> rebind,
2463 (unsigned)offered_lease_time);
2464 i = DHO_DHCP_REBINDING_TIME;
2465 if (lookup_option (&dhcp_universe, state -> options, i))
2466 log_error ("overriding dhcp-rebinding-time for %s.",
2467 inet_ntoa (state -> ciaddr));
2468 oc = (struct option_cache *)0;
2469 if (option_cache_allocate (&oc, MDL)) {
2470 if (make_const_data (&oc -> expression,
2471 (unsigned char *)&state -> rebind,
2472 sizeof state -> rebind,
2473 0, 0, MDL)) {
2474 oc -> option = dhcp_universe.options [i];
2475 save_option (&dhcp_universe,
2476 state -> options, oc);
2478 option_cache_dereference (&oc, MDL);
2480 } else {
2481 state -> from.len =
2482 sizeof state -> ip -> primary_address;
2483 memcpy (state -> from.iabuf,
2484 &state -> ip -> primary_address,
2485 state -> from.len);
2488 /* Figure out the address of the boot file server. */
2489 memcpy (&state -> siaddr, state -> from.iabuf, sizeof state -> siaddr);
2490 if ((oc =
2491 lookup_option (&server_universe,
2492 state -> options, SV_NEXT_SERVER))) {
2493 if (evaluate_option_cache (&d1, packet, lease,
2494 (struct client_state *)0,
2495 packet -> options, state -> options,
2496 &lease -> scope, oc, MDL)) {
2497 /* If there was more than one answer,
2498 take the first. */
2499 if (d1.len >= 4 && d1.data)
2500 memcpy (&state -> siaddr, d1.data, 4);
2501 data_string_forget (&d1, MDL);
2505 /* Use the subnet mask from the subnet declaration if no other
2506 mask has been provided. */
2507 i = DHO_SUBNET_MASK;
2508 if (!lookup_option (&dhcp_universe, state -> options, i)) {
2509 oc = (struct option_cache *)0;
2510 if (option_cache_allocate (&oc, MDL)) {
2511 if (make_const_data (&oc -> expression,
2512 lease -> subnet -> netmask.iabuf,
2513 lease -> subnet -> netmask.len,
2514 0, 0, MDL)) {
2515 oc -> option = dhcp_universe.options [i];
2516 save_option (&dhcp_universe,
2517 state -> options, oc);
2519 option_cache_dereference (&oc, MDL);
2523 /* Use the hostname from the host declaration if there is one
2524 and no hostname has otherwise been provided, and if the
2525 use-host-decl-name flag is set. */
2526 i = DHO_HOST_NAME;
2527 j = SV_USE_HOST_DECL_NAMES;
2528 if (!lookup_option (&dhcp_universe, state -> options, i) &&
2529 lease -> host && lease -> host -> name &&
2530 (evaluate_boolean_option_cache
2531 (&ignorep, packet, lease, (struct client_state *)0,
2532 packet -> options, state -> options, &lease -> scope,
2533 lookup_option (&server_universe, state -> options, j), MDL))) {
2534 oc = (struct option_cache *)0;
2535 if (option_cache_allocate (&oc, MDL)) {
2536 if (make_const_data (&oc -> expression,
2537 ((unsigned char *)
2538 lease -> host -> name),
2539 strlen (lease -> host -> name),
2540 1, 0, MDL)) {
2541 oc -> option = dhcp_universe.options [i];
2542 save_option (&dhcp_universe,
2543 state -> options, oc);
2545 option_cache_dereference (&oc, MDL);
2549 /* If we don't have a hostname yet, and we've been asked to do
2550 a reverse lookup to find the hostname, do it. */
2551 j = SV_GET_LEASE_HOSTNAMES;
2552 if (!lookup_option (&server_universe, state -> options, i) &&
2553 (evaluate_boolean_option_cache
2554 (&ignorep, packet, lease, (struct client_state *)0,
2555 packet -> options, state -> options, &lease -> scope,
2556 lookup_option (&server_universe, state -> options, j), MDL))) {
2557 struct in_addr ia;
2558 struct hostent *h;
2560 memcpy (&ia, lease -> ip_addr.iabuf, 4);
2562 h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
2563 if (!h)
2564 log_error ("No hostname for %s", inet_ntoa (ia));
2565 else {
2566 oc = (struct option_cache *)0;
2567 if (option_cache_allocate (&oc, MDL)) {
2568 if (make_const_data (&oc -> expression,
2569 ((unsigned char *)
2570 h -> h_name),
2571 strlen (h -> h_name) + 1,
2572 1, 1, MDL)) {
2573 oc -> option =
2574 dhcp_universe.options [i];
2575 save_option (&dhcp_universe,
2576 state -> options, oc);
2578 option_cache_dereference (&oc, MDL);
2583 /* If so directed, use the leased IP address as the router address.
2584 This supposedly makes Win95 machines ARP for all IP addresses,
2585 so if the local router does proxy arp, you win. */
2587 if (evaluate_boolean_option_cache
2588 (&ignorep, packet, lease, (struct client_state *)0,
2589 packet -> options, state -> options, &lease -> scope,
2590 lookup_option (&server_universe, state -> options,
2591 SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
2592 i = DHO_ROUTERS;
2593 oc = lookup_option (&dhcp_universe, state -> options, i);
2594 if (!oc) {
2595 oc = (struct option_cache *)0;
2596 if (option_cache_allocate (&oc, MDL)) {
2597 if (make_const_data (&oc -> expression,
2598 lease -> ip_addr.iabuf,
2599 lease -> ip_addr.len,
2600 0, 0, MDL)) {
2601 oc -> option =
2602 dhcp_universe.options [i];
2603 save_option (&dhcp_universe,
2604 state -> options, oc);
2606 option_cache_dereference (&oc, MDL);
2611 /* If a site option space has been specified, use that for
2612 site option codes. */
2613 i = SV_SITE_OPTION_SPACE;
2614 if ((oc = lookup_option (&server_universe, state -> options, i)) &&
2615 evaluate_option_cache (&d1, packet, lease,
2616 (struct client_state *)0,
2617 packet -> options, state -> options,
2618 &lease -> scope, oc, MDL)) {
2619 struct universe *u = (struct universe *)0;
2621 if (!universe_hash_lookup (&u, universe_hash,
2622 (const char *)d1.data, d1.len,
2623 MDL)) {
2624 log_error ("unknown option space %s.", d1.data);
2625 return;
2628 state -> options -> site_universe = u -> index;
2629 state -> options -> site_code_min = 128; /* XXX */
2630 data_string_forget (&d1, MDL);
2631 } else {
2632 state -> options -> site_code_min = 0;
2633 state -> options -> site_universe = dhcp_universe.index;
2636 /* If the client has provided a list of options that it wishes
2637 returned, use it to prioritize. If there's a parameter
2638 request list in scope, use that in preference. Otherwise
2639 use the default priority list. */
2641 oc = lookup_option (&dhcp_universe, state -> options,
2642 DHO_DHCP_PARAMETER_REQUEST_LIST);
2644 if (!oc)
2645 oc = lookup_option (&dhcp_universe, packet -> options,
2646 DHO_DHCP_PARAMETER_REQUEST_LIST);
2647 if (oc)
2648 evaluate_option_cache (&state -> parameter_request_list,
2649 packet, lease, (struct client_state *)0,
2650 packet -> options, state -> options,
2651 &lease -> scope, oc, MDL);
2653 #ifdef DEBUG_PACKET
2654 dump_packet (packet);
2655 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
2656 #endif
2658 lease -> state = state;
2660 log_info ("%s", msg);
2662 /* Hang the packet off the lease state. */
2663 packet_reference (&lease -> state -> packet, packet, MDL);
2665 /* If this is a DHCPOFFER, ping the lease address before actually
2666 sending the offer. */
2667 if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
2668 cur_time - lease -> timestamp > 60 &&
2669 (!(oc = lookup_option (&server_universe, state -> options,
2670 SV_PING_CHECKS)) ||
2671 evaluate_boolean_option_cache (&ignorep, packet, lease,
2672 (struct client_state *)0,
2673 packet -> options,
2674 state -> options,
2675 &lease -> scope, oc, MDL))) {
2676 lease -> timestamp = cur_time;
2677 icmp_echorequest (&lease -> ip_addr);
2679 /* Determine wether to use configured or default ping timeout.
2681 if ((oc = lookup_option (&server_universe, state -> options,
2682 SV_PING_TIMEOUT)) &&
2683 evaluate_option_cache (&d1, packet, lease, NULL,
2684 packet -> options,
2685 state -> options,
2686 &lease -> scope, oc, MDL)) {
2687 if (d1.len == sizeof (u_int32_t))
2688 ping_timeout = getULong (d1.data);
2689 else
2690 ping_timeout = DEFAULT_PING_TIMEOUT;
2692 data_string_forget (&d1, MDL);
2693 } else
2694 ping_timeout = DEFAULT_PING_TIMEOUT;
2696 #ifdef DEBUG
2697 log_debug ("Ping timeout: %ld", (long)ping_timeout);
2698 #endif
2700 add_timeout (cur_time + ping_timeout, lease_ping_timeout, lease,
2701 (tvref_t)lease_reference,
2702 (tvunref_t)lease_dereference);
2703 ++outstanding_pings;
2704 } else {
2705 lease -> timestamp = cur_time;
2706 dhcp_reply (lease);
2710 void dhcp_reply (lease)
2711 struct lease *lease;
2713 int bufs = 0;
2714 unsigned packet_length;
2715 struct dhcp_packet raw;
2716 struct sockaddr_in to;
2717 struct in_addr from;
2718 struct hardware hto;
2719 int result;
2720 int i;
2721 struct lease_state *state = lease -> state;
2722 int nulltp, bootpp, unicastp = 1;
2723 struct option_tag *ot, *not;
2724 struct data_string d1;
2725 struct option_cache *oc;
2726 const char *s;
2728 if (!state)
2729 log_fatal ("dhcp_reply was supplied lease with no state!");
2731 /* Compose a response for the client... */
2732 memset (&raw, 0, sizeof raw);
2733 memset (&d1, 0, sizeof d1);
2735 /* Copy in the filename if given; otherwise, flag the filename
2736 buffer as available for options. */
2737 if (state -> filename.len && state -> filename.data) {
2738 memcpy (raw.file,
2739 state -> filename.data,
2740 state -> filename.len > sizeof raw.file
2741 ? sizeof raw.file : state -> filename.len);
2742 if (sizeof raw.file > state -> filename.len)
2743 memset (&raw.file [state -> filename.len], 0,
2744 (sizeof raw.file) - state -> filename.len);
2745 } else
2746 bufs |= 1;
2748 /* Copy in the server name if given; otherwise, flag the
2749 server_name buffer as available for options. */
2750 if (state -> server_name.len && state -> server_name.data) {
2751 memcpy (raw.sname,
2752 state -> server_name.data,
2753 state -> server_name.len > sizeof raw.sname
2754 ? sizeof raw.sname : state -> server_name.len);
2755 if (sizeof raw.sname > state -> server_name.len)
2756 memset (&raw.sname [state -> server_name.len], 0,
2757 (sizeof raw.sname) - state -> server_name.len);
2758 } else
2759 bufs |= 2; /* XXX */
2761 memcpy (raw.chaddr,
2762 &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
2763 raw.hlen = lease -> hardware_addr.hlen - 1;
2764 raw.htype = lease -> hardware_addr.hbuf [0];
2766 /* See if this is a Microsoft client that NUL-terminates its
2767 strings and expects us to do likewise... */
2768 if (lease -> flags & MS_NULL_TERMINATION)
2769 nulltp = 1;
2770 else
2771 nulltp = 0;
2773 /* See if this is a bootp client... */
2774 if (state -> offer)
2775 bootpp = 0;
2776 else
2777 bootpp = 1;
2779 /* Insert such options as will fit into the buffer. */
2780 packet_length = cons_options (state -> packet, &raw, lease,
2781 (struct client_state *)0,
2782 state -> max_message_size,
2783 state -> packet -> options,
2784 state -> options, &global_scope,
2785 bufs, nulltp, bootpp,
2786 &state -> parameter_request_list,
2787 (char *)0);
2789 memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
2790 memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
2791 raw.siaddr = state -> siaddr;
2792 raw.giaddr = state -> giaddr;
2794 raw.xid = state -> xid;
2795 raw.secs = state -> secs;
2796 raw.flags = state -> bootp_flags;
2797 raw.hops = state -> hops;
2798 raw.op = BOOTREPLY;
2800 if (lease -> client_hostname) {
2801 if ((strlen (lease -> client_hostname) <= 64) &&
2802 db_printable (lease -> client_hostname))
2803 s = lease -> client_hostname;
2804 else
2805 s = "Hostname Unsuitable for Printing";
2806 } else
2807 s = (char *)0;
2809 /* Say what we're doing... */
2810 log_info ("%s on %s to %s %s%s%svia %s",
2811 (state -> offer
2812 ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
2813 : "BOOTREPLY"),
2814 piaddr (lease -> ip_addr),
2815 (lease -> hardware_addr.hlen
2816 ? print_hw_addr (lease -> hardware_addr.hbuf [0],
2817 lease -> hardware_addr.hlen - 1,
2818 &lease -> hardware_addr.hbuf [1])
2819 : print_hex_1 (lease -> uid_len, lease -> uid,
2820 lease -> uid_len)),
2821 s ? "(" : "", s ? s : "", s ? ") " : "",
2822 (state -> giaddr.s_addr
2823 ? inet_ntoa (state -> giaddr)
2824 : state -> ip -> name));
2826 /* Set up the hardware address... */
2827 hto.hlen = lease -> hardware_addr.hlen;
2828 memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
2830 to.sin_family = AF_INET;
2831 #ifdef HAVE_SA_LEN
2832 to.sin_len = sizeof to;
2833 #endif
2834 memset (to.sin_zero, 0, sizeof to.sin_zero);
2836 #ifdef DEBUG_PACKET
2837 dump_raw ((unsigned char *)&raw, packet_length);
2838 #endif
2840 /* Make sure outgoing packets are at least as big
2841 as a BOOTP packet. */
2842 if (packet_length < BOOTP_MIN_LEN)
2843 packet_length = BOOTP_MIN_LEN;
2845 /* If this was gatewayed, send it back to the gateway... */
2846 if (raw.giaddr.s_addr) {
2847 to.sin_addr = raw.giaddr;
2848 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
2849 to.sin_port = local_port;
2850 else
2851 to.sin_port = remote_port; /* For debugging. */
2853 if (fallback_interface) {
2854 result = send_packet (fallback_interface,
2855 (struct packet *)0,
2856 &raw, packet_length,
2857 raw.siaddr, &to,
2858 (struct hardware *)0);
2860 free_lease_state (state, MDL);
2861 lease -> state = (struct lease_state *)0;
2862 return;
2865 /* If the client is RENEWING, unicast to the client using the
2866 regular IP stack. Some clients, particularly those that
2867 follow RFC1541, are buggy, and send both ciaddr and server
2868 identifier. We deal with this situation by assuming that
2869 if we got both dhcp-server-identifier and ciaddr, and
2870 giaddr was not set, then the client is on the local
2871 network, and we can therefore unicast or broadcast to it
2872 successfully. A client in REQUESTING state on another
2873 network that's making this mistake will have set giaddr,
2874 and will therefore get a relayed response from the above
2875 code. */
2876 } else if (raw.ciaddr.s_addr &&
2877 !((state -> got_server_identifier ||
2878 (raw.flags & htons (BOOTP_BROADCAST))) &&
2879 /* XXX This won't work if giaddr isn't zero, but it is: */
2880 (state -> shared_network ==
2881 lease -> subnet -> shared_network)) &&
2882 state -> offer == DHCPACK) {
2883 to.sin_addr = raw.ciaddr;
2884 to.sin_port = remote_port;
2886 if (fallback_interface) {
2887 result = send_packet (fallback_interface,
2888 (struct packet *)0,
2889 &raw, packet_length,
2890 raw.siaddr, &to,
2891 (struct hardware *)0);
2892 free_lease_state (state, MDL);
2893 lease -> state = (struct lease_state *)0;
2894 return;
2897 /* If it comes from a client that already knows its address
2898 and is not requesting a broadcast response, and we can
2899 unicast to a client without using the ARP protocol, sent it
2900 directly to that client. */
2901 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
2902 can_unicast_without_arp (state -> ip)) {
2903 to.sin_addr = raw.yiaddr;
2904 to.sin_port = remote_port;
2906 /* Otherwise, broadcast it on the local network. */
2907 } else {
2908 to.sin_addr = limited_broadcast;
2909 to.sin_port = remote_port;
2910 if (!(lease -> flags & UNICAST_BROADCAST_HACK))
2911 unicastp = 0;
2914 memcpy (&from, state -> from.iabuf, sizeof from);
2916 result = send_packet (state -> ip,
2917 (struct packet *)0, &raw, packet_length,
2918 from, &to,
2919 unicastp ? &hto : (struct hardware *)0);
2921 /* Free all of the entries in the option_state structure
2922 now that we're done with them. */
2924 free_lease_state (state, MDL);
2925 lease -> state = (struct lease_state *)0;
2928 int find_lease (struct lease **lp,
2929 struct packet *packet, struct shared_network *share, int *ours,
2930 int *allocatedp, struct lease *ip_lease_in,
2931 const char *file, int line)
2933 struct lease *uid_lease = (struct lease *)0;
2934 struct lease *ip_lease = (struct lease *)0;
2935 struct lease *hw_lease = (struct lease *)0;
2936 struct lease *lease = (struct lease *)0;
2937 struct iaddr cip;
2938 struct host_decl *hp = (struct host_decl *)0;
2939 struct host_decl *host = (struct host_decl *)0;
2940 struct lease *fixed_lease = (struct lease *)0;
2941 struct lease *next = (struct lease *)0;
2942 struct option_cache *oc;
2943 struct data_string d1;
2944 int have_client_identifier = 0;
2945 struct data_string client_identifier;
2946 int status;
2947 struct hardware h;
2949 if (packet -> raw -> ciaddr.s_addr) {
2950 cip.len = 4;
2951 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
2952 } else {
2953 /* Look up the requested address. */
2954 oc = lookup_option (&dhcp_universe, packet -> options,
2955 DHO_DHCP_REQUESTED_ADDRESS);
2956 memset (&d1, 0, sizeof d1);
2957 if (oc &&
2958 evaluate_option_cache (&d1, packet, (struct lease *)0,
2959 (struct client_state *)0,
2960 packet -> options,
2961 (struct option_state *)0,
2962 &global_scope, oc, MDL)) {
2963 packet -> got_requested_address = 1;
2964 cip.len = 4;
2965 memcpy (cip.iabuf, d1.data, cip.len);
2966 data_string_forget (&d1, MDL);
2967 } else
2968 cip.len = 0;
2971 /* Try to find a host or lease that's been assigned to the
2972 specified unique client identifier. */
2973 oc = lookup_option (&dhcp_universe, packet -> options,
2974 DHO_DHCP_CLIENT_IDENTIFIER);
2975 memset (&client_identifier, 0, sizeof client_identifier);
2976 if (oc &&
2977 evaluate_option_cache (&client_identifier,
2978 packet, (struct lease *)0,
2979 (struct client_state *)0,
2980 packet -> options, (struct option_state *)0,
2981 &global_scope, oc, MDL)) {
2982 /* Remember this for later. */
2983 have_client_identifier = 1;
2985 /* First, try to find a fixed host entry for the specified
2986 client identifier... */
2987 if (find_hosts_by_uid (&hp, client_identifier.data,
2988 client_identifier.len, MDL)) {
2989 /* Remember if we know of this client. */
2990 packet -> known = 1;
2991 mockup_lease (&fixed_lease, packet, share, hp);
2994 #if defined (DEBUG_FIND_LEASE)
2995 if (fixed_lease) {
2996 log_info ("Found host for client identifier: %s.",
2997 piaddr (fixed_lease -> ip_addr));
2999 #endif
3000 if (hp) {
3001 if (!fixed_lease) /* Save the host if we found one. */
3002 host_reference (&host, hp, MDL);
3003 host_dereference (&hp, MDL);
3006 find_lease_by_uid (&uid_lease, client_identifier.data,
3007 client_identifier.len, MDL);
3010 /* If we didn't find a fixed lease using the uid, try doing
3011 it with the hardware address... */
3012 if (!fixed_lease && !host) {
3013 if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
3014 packet -> raw -> chaddr,
3015 packet -> raw -> hlen, MDL)) {
3016 /* Remember if we know of this client. */
3017 packet -> known = 1;
3018 if (host)
3019 host_dereference (&host, MDL);
3020 host_reference (&host, hp, MDL);
3021 host_dereference (&hp, MDL);
3022 mockup_lease (&fixed_lease, packet, share, host);
3023 #if defined (DEBUG_FIND_LEASE)
3024 if (fixed_lease) {
3025 log_info ("Found host for link address: %s.",
3026 piaddr (fixed_lease -> ip_addr));
3028 #endif
3032 /* If fixed_lease is present but does not match the requested
3033 IP address, and this is a DHCPREQUEST, then we can't return
3034 any other lease, so we might as well return now. */
3035 if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
3036 (fixed_lease -> ip_addr.len != cip.len ||
3037 memcmp (fixed_lease -> ip_addr.iabuf,
3038 cip.iabuf, cip.len))) {
3039 if (ours)
3040 *ours = 1;
3041 strcpy (dhcp_message, "requested address is incorrect");
3042 #if defined (DEBUG_FIND_LEASE)
3043 log_info ("Client's fixed-address %s doesn't match %s%s",
3044 piaddr (fixed_lease -> ip_addr), "request ",
3045 print_dotted_quads (cip.len, cip.iabuf));
3046 #endif
3047 goto out;
3050 /* If we found leases matching the client identifier, loop through
3051 the n_uid pointer looking for one that's actually valid. We
3052 can't do this until we get here because we depend on
3053 packet -> known, which may be set by either the uid host
3054 lookup or the haddr host lookup. */
3055 while (uid_lease) {
3056 #if defined (DEBUG_FIND_LEASE)
3057 log_info ("trying next lease matching client id: %s",
3058 piaddr (uid_lease -> ip_addr));
3059 #endif
3061 #if defined (FAILOVER_PROTOCOL)
3062 /* When failover is active, it's possible that there could
3063 be two "free" leases for the same uid, but only one of
3064 them that's available for this failover peer to allocate. */
3065 if (uid_lease -> binding_state != FTS_ACTIVE &&
3066 !lease_mine_to_reallocate (uid_lease)) {
3067 #if defined (DEBUG_FIND_LEASE)
3068 log_info ("not mine to allocate: %s",
3069 piaddr (uid_lease -> ip_addr));
3070 #endif
3071 goto n_uid;
3073 #endif
3075 if (uid_lease -> subnet -> shared_network != share) {
3076 #if defined (DEBUG_FIND_LEASE)
3077 log_info ("wrong network segment: %s",
3078 piaddr (uid_lease -> ip_addr));
3079 #endif
3080 goto n_uid;
3083 if ((uid_lease -> pool -> prohibit_list &&
3084 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
3085 (uid_lease -> pool -> permit_list &&
3086 !permitted (packet, uid_lease -> pool -> permit_list))) {
3087 #if defined (DEBUG_FIND_LEASE)
3088 log_info ("not permitted: %s",
3089 piaddr (uid_lease -> ip_addr));
3090 #endif
3091 n_uid:
3092 if (uid_lease -> n_uid)
3093 lease_reference (&next,
3094 uid_lease -> n_uid, MDL);
3095 if (!packet -> raw -> ciaddr.s_addr)
3096 release_lease (uid_lease, packet);
3097 lease_dereference (&uid_lease, MDL);
3098 if (next) {
3099 lease_reference (&uid_lease, next, MDL);
3100 lease_dereference (&next, MDL);
3102 continue;
3104 break;
3106 #if defined (DEBUG_FIND_LEASE)
3107 if (uid_lease)
3108 log_info ("Found lease for client id: %s.",
3109 piaddr (uid_lease -> ip_addr));
3110 #endif
3112 /* Find a lease whose hardware address matches, whose client
3113 identifier matches, that's permitted, and that's on the
3114 correct subnet. */
3115 h.hlen = packet -> raw -> hlen + 1;
3116 h.hbuf [0] = packet -> raw -> htype;
3117 memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
3118 find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
3119 while (hw_lease) {
3120 #if defined (DEBUG_FIND_LEASE)
3121 log_info ("trying next lease matching hw addr: %s",
3122 piaddr (hw_lease -> ip_addr));
3123 #endif
3124 #if defined (FAILOVER_PROTOCOL)
3125 /* When failover is active, it's possible that there could
3126 be two "free" leases for the same uid, but only one of
3127 them that's available for this failover peer to allocate. */
3128 if (hw_lease -> binding_state != FTS_ACTIVE &&
3129 !lease_mine_to_reallocate (hw_lease)) {
3130 #if defined (DEBUG_FIND_LEASE)
3131 log_info ("not mine to allocate: %s",
3132 piaddr (hw_lease -> ip_addr));
3133 #endif
3134 goto n_hw;
3136 #endif
3138 if (hw_lease -> binding_state != FTS_FREE &&
3139 hw_lease -> binding_state != FTS_BACKUP &&
3140 hw_lease -> uid &&
3141 (!have_client_identifier ||
3142 hw_lease -> uid_len != client_identifier.len ||
3143 memcmp (hw_lease -> uid, client_identifier.data,
3144 hw_lease -> uid_len))) {
3145 #if defined (DEBUG_FIND_LEASE)
3146 log_info ("wrong client identifier: %s",
3147 piaddr (hw_lease -> ip_addr));
3148 #endif
3149 goto n_hw;
3150 continue;
3152 if (hw_lease -> subnet -> shared_network != share) {
3153 #if defined (DEBUG_FIND_LEASE)
3154 log_info ("wrong network segment: %s",
3155 piaddr (hw_lease -> ip_addr));
3156 #endif
3157 goto n_hw;
3158 continue;
3160 if ((hw_lease -> pool -> prohibit_list &&
3161 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
3162 (hw_lease -> pool -> permit_list &&
3163 !permitted (packet, hw_lease -> pool -> permit_list))) {
3164 #if defined (DEBUG_FIND_LEASE)
3165 log_info ("not permitted: %s",
3166 piaddr (hw_lease -> ip_addr));
3167 #endif
3168 if (!packet -> raw -> ciaddr.s_addr)
3169 release_lease (hw_lease, packet);
3170 n_hw:
3171 if (hw_lease -> n_hw)
3172 lease_reference (&next, hw_lease -> n_hw, MDL);
3173 lease_dereference (&hw_lease, MDL);
3174 if (next) {
3175 lease_reference (&hw_lease, next, MDL);
3176 lease_dereference (&next, MDL);
3178 continue;
3180 break;
3182 #if defined (DEBUG_FIND_LEASE)
3183 if (hw_lease)
3184 log_info ("Found lease for hardware address: %s.",
3185 piaddr (hw_lease -> ip_addr));
3186 #endif
3188 /* Try to find a lease that's been allocated to the client's
3189 IP address. */
3190 if (ip_lease_in)
3191 lease_reference (&ip_lease, ip_lease_in, MDL);
3192 else if (cip.len)
3193 find_lease_by_ip_addr (&ip_lease, cip, MDL);
3195 #if defined (DEBUG_FIND_LEASE)
3196 if (ip_lease)
3197 log_info ("Found lease for requested address: %s.",
3198 piaddr (ip_lease -> ip_addr));
3199 #endif
3201 /* If ip_lease is valid at this point, set ours to one, so that
3202 even if we choose a different lease, we know that the address
3203 the client was requesting was ours, and thus we can NAK it. */
3204 if (ip_lease && ours)
3205 *ours = 1;
3207 /* If the requested IP address isn't on the network the packet
3208 came from, don't use it. Allow abandoned leases to be matched
3209 here - if the client is requesting it, there's a decent chance
3210 that it's because the lease database got trashed and a client
3211 that thought it had this lease answered an ARP or PING, causing the
3212 lease to be abandoned. If so, this request probably came from
3213 that client. */
3214 if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
3215 if (ours)
3216 *ours = 1;
3217 #if defined (DEBUG_FIND_LEASE)
3218 log_info ("...but it was on the wrong shared network.");
3219 #endif
3220 strcpy (dhcp_message, "requested address on bad subnet");
3221 lease_dereference (&ip_lease, MDL);
3224 /* Toss ip_lease if it hasn't yet expired and doesn't belong to the
3225 client. */
3226 if (ip_lease &&
3227 (ip_lease -> uid ?
3228 (!have_client_identifier ||
3229 ip_lease -> uid_len != client_identifier.len ||
3230 memcmp (ip_lease -> uid, client_identifier.data,
3231 ip_lease -> uid_len)) :
3232 (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
3233 ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
3234 memcmp (&ip_lease -> hardware_addr.hbuf [1],
3235 packet -> raw -> chaddr,
3236 (unsigned)(ip_lease -> hardware_addr.hlen - 1))))) {
3237 /* If we're not doing failover, the only state in which
3238 we can allocate this lease to the client is FTS_FREE.
3239 If we are doing failover, things are more complicated.
3240 If the lease is free or backup, we let the caller decide
3241 whether or not to give it out. */
3242 if (ip_lease -> binding_state != FTS_FREE &&
3243 ip_lease -> binding_state != FTS_BACKUP) {
3244 #if defined (DEBUG_FIND_LEASE)
3245 log_info ("rejecting lease for requested address.");
3246 #endif
3247 /* If we're rejecting it because the peer has
3248 it, don't set "ours", because we shouldn't NAK. */
3249 if (ours && ip_lease -> binding_state != FTS_ACTIVE)
3250 *ours = 0;
3251 lease_dereference (&ip_lease, MDL);
3252 } else
3253 if (allocatedp)
3254 *allocatedp = 1;
3257 /* If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
3258 is not active, and is not ours to reallocate, forget about it. */
3259 if (ip_lease && (uid_lease || hw_lease) &&
3260 ip_lease -> binding_state != FTS_ACTIVE &&
3261 !lease_mine_to_reallocate (ip_lease) &&
3262 packet -> packet_type == DHCPDISCOVER) {
3263 #if defined (DEBUG_FIND_LEASE)
3264 log_info ("ip lease not ours to offer.");
3265 #endif
3266 lease_dereference (&ip_lease, MDL);
3269 /* If for some reason the client has more than one lease
3270 on the subnet that matches its uid, pick the one that
3271 it asked for and (if we can) free the other. */
3272 if (ip_lease &&
3273 ip_lease -> binding_state == FTS_ACTIVE &&
3274 ip_lease -> uid && ip_lease != uid_lease) {
3275 if (have_client_identifier &&
3276 (ip_lease -> uid_len == client_identifier.len) &&
3277 !memcmp (client_identifier.data,
3278 ip_lease -> uid, ip_lease -> uid_len)) {
3279 if (uid_lease) {
3280 if (uid_lease -> binding_state == FTS_ACTIVE) {
3281 log_error ("client %s has duplicate%s on %s",
3282 (print_hw_addr
3283 (packet -> raw -> htype,
3284 packet -> raw -> hlen,
3285 packet -> raw -> chaddr)),
3286 " leases",
3287 (ip_lease -> subnet ->
3288 shared_network -> name));
3290 /* If the client is REQUESTing the lease,
3291 it shouldn't still be using the old
3292 one, so we can free it for allocation. */
3293 if (uid_lease &&
3294 uid_lease -> binding_state == FTS_ACTIVE &&
3295 !packet -> raw -> ciaddr.s_addr &&
3296 (share ==
3297 uid_lease -> subnet -> shared_network) &&
3298 packet -> packet_type == DHCPREQUEST)
3299 dissociate_lease (uid_lease);
3301 lease_dereference (&uid_lease, MDL);
3302 lease_reference (&uid_lease, ip_lease, MDL);
3306 /* If we get to here and fixed_lease is not null, that means
3307 that there are both a dynamic lease and a fixed-address
3308 declaration for the same IP address. */
3309 if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
3310 lease_dereference (&fixed_lease, MDL);
3311 db_conflict:
3312 log_error ("Dynamic and static leases present for %s.",
3313 piaddr (cip));
3314 log_error ("Remove host declaration %s or remove %s",
3315 (fixed_lease && fixed_lease -> host
3316 ? (fixed_lease -> host -> name
3317 ? fixed_lease -> host -> name
3318 : piaddr (cip))
3319 : piaddr (cip)),
3320 piaddr (cip));
3321 log_error ("from the dynamic address pool for %s",
3322 ip_lease -> subnet -> shared_network -> name
3324 if (fixed_lease)
3325 lease_dereference (&ip_lease, MDL);
3326 strcpy (dhcp_message,
3327 "database conflict - call for help!");
3330 if (ip_lease && ip_lease != uid_lease) {
3331 #if defined (DEBUG_FIND_LEASE)
3332 log_info ("requested address not available.");
3333 #endif
3334 lease_dereference (&ip_lease, MDL);
3338 /* If we get to here with both fixed_lease and ip_lease not
3339 null, then we have a configuration file bug. */
3340 if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
3341 goto db_conflict;
3343 /* Toss extra pointers to the same lease... */
3344 if (hw_lease && hw_lease == uid_lease) {
3345 #if defined (DEBUG_FIND_LEASE)
3346 log_info ("hardware lease and uid lease are identical.");
3347 #endif
3348 lease_dereference (&hw_lease, MDL);
3350 if (ip_lease && ip_lease == hw_lease) {
3351 lease_dereference (&hw_lease, MDL);
3352 #if defined (DEBUG_FIND_LEASE)
3353 log_info ("hardware lease and ip lease are identical.");
3354 #endif
3356 if (ip_lease && ip_lease == uid_lease) {
3357 lease_dereference (&uid_lease, MDL);
3358 #if defined (DEBUG_FIND_LEASE)
3359 log_info ("uid lease and ip lease are identical.");
3360 #endif
3363 /* Make sure the client is permitted to use the requested lease. */
3364 if (ip_lease &&
3365 ((ip_lease -> pool -> prohibit_list &&
3366 permitted (packet, ip_lease -> pool -> prohibit_list)) ||
3367 (ip_lease -> pool -> permit_list &&
3368 !permitted (packet, ip_lease -> pool -> permit_list)))) {
3369 if (!packet -> raw -> ciaddr.s_addr)
3370 release_lease (ip_lease, packet);
3371 lease_dereference (&ip_lease, MDL);
3374 if (uid_lease &&
3375 ((uid_lease -> pool -> prohibit_list &&
3376 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
3377 (uid_lease -> pool -> permit_list &&
3378 !permitted (packet, uid_lease -> pool -> permit_list)))) {
3379 if (!packet -> raw -> ciaddr.s_addr)
3380 release_lease (uid_lease, packet);
3381 lease_dereference (&uid_lease, MDL);
3384 if (hw_lease &&
3385 ((hw_lease -> pool -> prohibit_list &&
3386 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
3387 (hw_lease -> pool -> permit_list &&
3388 !permitted (packet, hw_lease -> pool -> permit_list)))) {
3389 if (!packet -> raw -> ciaddr.s_addr)
3390 release_lease (hw_lease, packet);
3391 lease_dereference (&hw_lease, MDL);
3394 /* If we've already eliminated the lease, it wasn't there to
3395 begin with. If we have come up with a matching lease,
3396 set the message to bad network in case we have to throw it out. */
3397 if (!ip_lease) {
3398 strcpy (dhcp_message, "requested address not available");
3401 /* If this is a DHCPREQUEST, make sure the lease we're going to return
3402 matches the requested IP address. If it doesn't, don't return a
3403 lease at all. */
3404 if (packet -> packet_type == DHCPREQUEST &&
3405 !ip_lease && !fixed_lease) {
3406 #if defined (DEBUG_FIND_LEASE)
3407 log_info ("no applicable lease found for DHCPREQUEST.");
3408 #endif
3409 goto out;
3412 /* At this point, if fixed_lease is nonzero, we can assign it to
3413 this client. */
3414 if (fixed_lease) {
3415 lease_reference (&lease, fixed_lease, MDL);
3416 lease_dereference (&fixed_lease, MDL);
3417 #if defined (DEBUG_FIND_LEASE)
3418 log_info ("choosing fixed address.");
3419 #endif
3422 /* If we got a lease that matched the ip address and don't have
3423 a better offer, use that; otherwise, release it. */
3424 if (ip_lease) {
3425 if (lease) {
3426 if (!packet -> raw -> ciaddr.s_addr)
3427 release_lease (ip_lease, packet);
3428 #if defined (DEBUG_FIND_LEASE)
3429 log_info ("not choosing requested address (!).");
3430 #endif
3431 } else {
3432 #if defined (DEBUG_FIND_LEASE)
3433 log_info ("choosing lease on requested address.");
3434 #endif
3435 lease_reference (&lease, ip_lease, MDL);
3436 if (lease -> host)
3437 host_dereference (&lease -> host, MDL);
3439 lease_dereference (&ip_lease, MDL);
3442 /* If we got a lease that matched the client identifier, we may want
3443 to use it, but if we already have a lease we like, we must free
3444 the lease that matched the client identifier. */
3445 if (uid_lease) {
3446 if (lease) {
3447 if (!packet -> raw -> ciaddr.s_addr &&
3448 packet -> packet_type == DHCPREQUEST &&
3449 uid_lease -> binding_state == FTS_ACTIVE)
3450 dissociate_lease (uid_lease);
3451 #if defined (DEBUG_FIND_LEASE)
3452 log_info ("not choosing uid lease.");
3453 #endif
3454 } else {
3455 lease_reference (&lease, uid_lease, MDL);
3456 if (lease -> host)
3457 host_dereference (&lease -> host, MDL);
3458 #if defined (DEBUG_FIND_LEASE)
3459 log_info ("choosing uid lease.");
3460 #endif
3462 lease_dereference (&uid_lease, MDL);
3465 /* The lease that matched the hardware address is treated likewise. */
3466 if (hw_lease) {
3467 if (lease) {
3468 #if defined (DEBUG_FIND_LEASE)
3469 log_info ("not choosing hardware lease.");
3470 #endif
3471 } else {
3472 /* We're a little lax here - if the client didn't
3473 send a client identifier and it's a bootp client,
3474 but the lease has a client identifier, we still
3475 let the client have a lease. */
3476 if (!hw_lease -> uid_len ||
3477 (have_client_identifier
3478 ? (hw_lease -> uid_len ==
3479 client_identifier.len &&
3480 !memcmp (hw_lease -> uid,
3481 client_identifier.data,
3482 client_identifier.len))
3483 : packet -> packet_type == 0)) {
3484 lease_reference (&lease, hw_lease, MDL);
3485 if (lease -> host)
3486 host_dereference (&lease -> host, MDL);
3487 #if defined (DEBUG_FIND_LEASE)
3488 log_info ("choosing hardware lease.");
3489 #endif
3490 } else {
3491 #if defined (DEBUG_FIND_LEASE)
3492 log_info ("not choosing hardware lease: %s.",
3493 "uid mismatch");
3494 #endif
3497 lease_dereference (&hw_lease, MDL);
3500 /* If we found a host_decl but no matching address, try to
3501 find a host_decl that has no address, and if there is one,
3502 hang it off the lease so that we can use the supplied
3503 options. */
3504 if (lease && host && !lease -> host) {
3505 struct host_decl *p = (struct host_decl *)0;
3506 struct host_decl *n = (struct host_decl *)0;
3507 host_reference (&p, host, MDL);
3508 while (p) {
3509 if (!p -> fixed_addr) {
3510 host_reference (&lease -> host, p, MDL);
3511 host_dereference (&p, MDL);
3512 break;
3514 if (p -> n_ipaddr)
3515 host_reference (&n, p -> n_ipaddr, MDL);
3516 host_dereference (&p, MDL);
3517 if (n) {
3518 host_reference (&p, n, MDL);
3519 host_dereference (&n, MDL);
3524 /* If we find an abandoned lease, but it's the one the client
3525 requested, we assume that previous bugginess on the part
3526 of the client, or a server database loss, caused the lease to
3527 be abandoned, so we reclaim it and let the client have it. */
3528 if (lease &&
3529 (lease -> binding_state == FTS_ABANDONED) &&
3530 lease == ip_lease &&
3531 packet -> packet_type == DHCPREQUEST) {
3532 log_error ("Reclaiming REQUESTed abandoned IP address %s.",
3533 piaddr (lease -> ip_addr));
3534 } else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
3535 /* Otherwise, if it's not the one the client requested, we do not
3536 return it - instead, we claim it's ours, causing a DHCPNAK to be
3537 sent if this lookup is for a DHCPREQUEST, and force the client
3538 to go back through the allocation process. */
3539 if (ours)
3540 *ours = 1;
3541 lease_dereference (&lease, MDL);
3544 if (lease && allocatedp && lease -> ends <= cur_time)
3545 *allocatedp = 1;
3547 out:
3548 if (have_client_identifier)
3549 data_string_forget (&client_identifier, MDL);
3551 if (fixed_lease)
3552 lease_dereference (&fixed_lease, MDL);
3553 if (hw_lease)
3554 lease_dereference (&hw_lease, MDL);
3555 if (uid_lease)
3556 lease_dereference (&uid_lease, MDL);
3557 if (ip_lease)
3558 lease_dereference (&ip_lease, MDL);
3559 if (host)
3560 host_dereference (&host, MDL);
3562 if (lease) {
3563 #if defined (DEBUG_FIND_LEASE)
3564 log_info ("Returning lease: %s.",
3565 piaddr (lease -> ip_addr));
3566 #endif
3567 lease_reference (lp, lease, file, line);
3568 lease_dereference (&lease, MDL);
3569 return 1;
3571 #if defined (DEBUG_FIND_LEASE)
3572 log_info ("Not returning a lease.");
3573 #endif
3574 return 0;
3577 /* Search the provided host_decl structure list for an address that's on
3578 the specified shared network. If one is found, mock up and return a
3579 lease structure for it; otherwise return the null pointer. */
3581 int mockup_lease (struct lease **lp, struct packet *packet,
3582 struct shared_network *share, struct host_decl *hp)
3584 struct lease *lease = (struct lease *)0;
3585 const unsigned char **s;
3586 isc_result_t status;
3587 struct host_decl *rhp = (struct host_decl *)0;
3589 status = lease_allocate (&lease, MDL);
3590 if (status != ISC_R_SUCCESS)
3591 return 0;
3592 if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS)
3593 return 0;
3594 if (!find_host_for_network (&lease -> subnet,
3595 &rhp, &lease -> ip_addr, share)) {
3596 lease_dereference (&lease, MDL);
3597 return 0;
3599 host_reference (&lease -> host, rhp, MDL);
3600 if (rhp -> client_identifier.len > sizeof lease -> uid_buf)
3601 lease -> uid = dmalloc (rhp -> client_identifier.len, MDL);
3602 else
3603 lease -> uid = lease -> uid_buf;
3604 if (!lease -> uid) {
3605 lease_dereference (&lease, MDL);
3606 host_dereference (&rhp, MDL);
3607 return 0;
3609 memcpy (lease -> uid, rhp -> client_identifier.data,
3610 rhp -> client_identifier.len);
3611 lease -> uid_len = rhp -> client_identifier.len;
3612 lease -> hardware_addr = rhp -> interface;
3613 lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
3614 lease -> flags = STATIC_LEASE;
3615 lease -> binding_state = FTS_FREE;
3616 lease_reference (lp, lease, MDL);
3617 lease_dereference (&lease, MDL);
3618 host_dereference (&rhp, MDL);
3619 return 1;
3622 /* Look through all the pools in a list starting with the specified pool
3623 for a free lease. We try to find a virgin lease if we can. If we
3624 don't find a virgin lease, we try to find a non-virgin lease that's
3625 free. If we can't find one of those, we try to reclaim an abandoned
3626 lease. If all of these possibilities fail to pan out, we don't return
3627 a lease at all. */
3629 int allocate_lease (struct lease **lp, struct packet *packet,
3630 struct pool *pool, int *peer_has_leases)
3632 struct lease *lease = (struct lease *)0;
3633 struct lease *candl = (struct lease *)0;
3635 for (; pool ; pool = pool -> next) {
3636 if ((pool -> prohibit_list &&
3637 permitted (packet, pool -> prohibit_list)) ||
3638 (pool -> permit_list &&
3639 !permitted (packet, pool -> permit_list)))
3640 continue;
3642 #if defined (FAILOVER_PROTOCOL)
3643 /* Peer_has_leases just says that we found at least one
3644 free lease. If no free lease is returned, the caller
3645 can deduce that this means the peer is hogging all the
3646 free leases, so we can print a better error message. */
3647 /* XXX Do we need code here to ignore PEER_IS_OWNER and
3648 * XXX just check tstp if we're in, e.g., PARTNER_DOWN?
3649 * XXX Where do we deal with CONFLICT_DETECTED, et al? */
3650 /* XXX This should be handled by the lease binding "state
3651 * XXX machine" - that is, when we get here, if a lease
3652 * XXX could be allocated, it will have the correct
3653 * XXX binding state so that the following code will
3654 * XXX result in its being allocated. */
3655 /* Skip to the most expired lease in the pool that is not
3656 * owned by a failover peer. */
3657 if (pool -> failover_peer) {
3658 if (pool -> failover_peer -> i_am == primary) {
3659 if (pool -> backup)
3660 *peer_has_leases = 1;
3661 candl = pool -> free;
3662 if (!candl)
3663 candl = pool -> abandoned;
3664 } else {
3665 if (pool -> free)
3666 *peer_has_leases = 1;
3667 candl = pool -> backup;
3669 } else
3670 #endif
3672 if (pool -> free)
3673 candl = pool -> free;
3674 else
3675 candl = pool -> abandoned;
3678 if (!candl || (candl -> ends > cur_time))
3679 continue;
3681 if (!lease) {
3682 lease = candl;
3683 continue;
3686 if ((lease -> binding_state == FTS_ABANDONED) &&
3687 ((candl -> binding_state != FTS_ABANDONED) ||
3688 (candl -> ends < lease -> ends))) {
3689 lease = candl;
3690 continue;
3691 } else if (candl -> binding_state == FTS_ABANDONED)
3692 continue;
3694 if ((lease -> uid_len || lease -> hardware_addr.hlen) &&
3695 ((!candl -> uid_len && !candl -> hardware_addr.hlen) ||
3696 (candl -> ends < lease -> ends))) {
3697 lease = candl;
3698 continue;
3699 } else if (candl -> uid_len || candl -> hardware_addr.hlen)
3700 continue;
3702 if (candl -> ends < lease -> ends)
3703 lease = candl;
3706 if (lease) {
3707 if (lease -> binding_state == FTS_ABANDONED)
3708 log_error ("Reclaiming abandoned lease %s.",
3709 piaddr (lease -> ip_addr));
3711 lease_reference (lp, lease, MDL);
3712 return 1;
3715 return 0;
3718 /* Determine whether or not a permit exists on a particular permit list
3719 that matches the specified packet, returning nonzero if so, zero if
3720 not. */
3722 int permitted (packet, permit_list)
3723 struct packet *packet;
3724 struct permit *permit_list;
3726 struct permit *p;
3727 int i;
3729 for (p = permit_list; p; p = p -> next) {
3730 switch (p -> type) {
3731 case permit_unknown_clients:
3732 if (!packet -> known)
3733 return 1;
3734 break;
3736 case permit_known_clients:
3737 if (packet -> known)
3738 return 1;
3739 break;
3741 case permit_authenticated_clients:
3742 if (packet -> authenticated)
3743 return 1;
3744 break;
3746 case permit_unauthenticated_clients:
3747 if (!packet -> authenticated)
3748 return 1;
3749 break;
3751 case permit_all_clients:
3752 return 1;
3754 case permit_dynamic_bootp_clients:
3755 if (!packet -> options_valid ||
3756 !packet -> packet_type)
3757 return 1;
3758 break;
3760 case permit_class:
3761 for (i = 0; i < packet -> class_count; i++) {
3762 if (p -> class == packet -> classes [i])
3763 return 1;
3764 if (packet -> classes [i] &&
3765 packet -> classes [i] -> superclass &&
3766 (packet -> classes [i] -> superclass ==
3767 p -> class))
3768 return 1;
3770 break;
3773 return 0;
3776 int locate_network (packet)
3777 struct packet *packet;
3779 struct iaddr ia;
3780 struct data_string data;
3781 struct subnet *subnet = (struct subnet *)0;
3782 struct option_cache *oc;
3784 /* See if there's a subnet selection option. */
3785 oc = lookup_option (&dhcp_universe, packet -> options,
3786 DHO_SUBNET_SELECTION);
3788 /* If there's no SSO and no giaddr, then use the shared_network
3789 from the interface, if there is one. If not, fail. */
3790 if (!oc && !packet -> raw -> giaddr.s_addr) {
3791 if (packet -> interface -> shared_network) {
3792 shared_network_reference
3793 (&packet -> shared_network,
3794 packet -> interface -> shared_network, MDL);
3795 return 1;
3797 return 0;
3800 /* If there's an SSO, and it's valid, use it to figure out the
3801 subnet. If it's not valid, fail. */
3802 if (oc) {
3803 memset (&data, 0, sizeof data);
3804 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
3805 (struct client_state *)0,
3806 packet -> options,
3807 (struct option_state *)0,
3808 &global_scope, oc, MDL)) {
3809 return 0;
3811 if (data.len != 4) {
3812 return 0;
3814 ia.len = 4;
3815 memcpy (ia.iabuf, data.data, 4);
3816 data_string_forget (&data, MDL);
3817 } else {
3818 ia.len = 4;
3819 memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
3822 /* If we know the subnet on which the IP address lives, use it. */
3823 if (find_subnet (&subnet, ia, MDL)) {
3824 shared_network_reference (&packet -> shared_network,
3825 subnet -> shared_network, MDL);
3826 subnet_dereference (&subnet, MDL);
3827 return 1;
3830 /* Otherwise, fail. */
3831 return 0;