revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / stacks / AROSTCP / dhcp / server / dhcp.c
blobe35249cfbe228c88844ad8e380a6991ac72e54e8
1 /* dhcp.c
3 DHCP Protocol engine. */
5 /*
6 * Copyright (c) 2004-2005 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$ Copyright (c) 2004-2005 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 (struct host_decl *)0);
392 out:
393 if (lease)
394 lease_dereference (&lease, MDL);
397 void dhcprequest (packet, ms_nulltp, ip_lease)
398 struct packet *packet;
399 int ms_nulltp;
400 struct lease *ip_lease;
402 struct lease *lease;
403 struct iaddr cip;
404 struct iaddr sip;
405 struct subnet *subnet;
406 int ours = 0;
407 struct option_cache *oc;
408 struct data_string data;
409 int status;
410 char msgbuf [1024]; /* XXX */
411 const char *s;
412 char smbuf [19];
413 #if defined (FAILOVER_PROTOCOL)
414 dhcp_failover_state_t *peer;
415 #endif
416 int have_server_identifier = 0;
417 int have_requested_addr = 0;
419 oc = lookup_option (&dhcp_universe, packet -> options,
420 DHO_DHCP_REQUESTED_ADDRESS);
421 memset (&data, 0, sizeof data);
422 if (oc &&
423 evaluate_option_cache (&data, packet, (struct lease *)0,
424 (struct client_state *)0,
425 packet -> options, (struct option_state *)0,
426 &global_scope, oc, MDL)) {
427 cip.len = 4;
428 memcpy (cip.iabuf, data.data, 4);
429 data_string_forget (&data, MDL);
430 have_requested_addr = 1;
431 } else {
432 oc = (struct option_cache *)0;
433 cip.len = 4;
434 memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
437 /* Find the lease that matches the address requested by the
438 client. */
440 subnet = (struct subnet *)0;
441 lease = (struct lease *)0;
442 if (find_subnet (&subnet, cip, MDL))
443 find_lease (&lease, packet,
444 subnet -> shared_network, &ours, 0, ip_lease, MDL);
445 /* XXX consider using allocatedp arg to find_lease to see
446 XXX that this isn't a compliant DHCPREQUEST. */
448 if (lease && lease -> client_hostname) {
449 if ((strlen (lease -> client_hostname) <= 64) &&
450 db_printable (lease -> client_hostname))
451 s = lease -> client_hostname;
452 else
453 s = "Hostname Unsuitable for Printing";
454 } else
455 s = (char *)0;
457 oc = lookup_option (&dhcp_universe, packet -> options,
458 DHO_DHCP_SERVER_IDENTIFIER);
459 memset (&data, 0, sizeof data);
460 if (oc &&
461 evaluate_option_cache (&data, packet, (struct lease *)0,
462 (struct client_state *)0,
463 packet -> options, (struct option_state *)0,
464 &global_scope, oc, MDL)) {
465 sip.len = 4;
466 memcpy (sip.iabuf, data.data, 4);
467 data_string_forget (&data, MDL);
468 /* piaddr() should not return more than a 15 byte string.
469 * safe.
471 sprintf (smbuf, " (%s)", piaddr (sip));
472 have_server_identifier = 1;
473 } else
474 smbuf [0] = 0;
476 /* %Audit% This is log output. %2004.06.17,Safe%
477 * If we truncate we hope the user can get a hint from the log.
479 snprintf (msgbuf, sizeof msgbuf,
480 "DHCPREQUEST for %s%s from %s %s%s%svia %s",
481 piaddr (cip), smbuf,
482 (packet -> raw -> htype
483 ? print_hw_addr (packet -> raw -> htype,
484 packet -> raw -> hlen,
485 packet -> raw -> chaddr)
486 : (lease
487 ? print_hex_1 (lease -> uid_len, lease -> uid,
488 lease -> uid_len)
489 : "<no identifier>")),
490 s ? "(" : "", s ? s : "", s ? ") " : "",
491 packet -> raw -> giaddr.s_addr
492 ? inet_ntoa (packet -> raw -> giaddr)
493 : packet -> interface -> name);
495 #if defined (FAILOVER_PROTOCOL)
496 if (lease && lease -> pool && lease -> pool -> failover_peer) {
497 peer = lease -> pool -> failover_peer;
498 if (peer -> service_state == not_responding ||
499 peer -> service_state == service_startup) {
500 log_info ("%s: not responding%s",
501 msgbuf, peer -> nrr);
502 goto out;
505 /* "load balance to peer" - is not done at all for request.
507 * If it's RENEWING, we are the only server to hear it, so
508 * we have to serve it. If it's REBINDING, it's out of
509 * communication with the other server, so there's no point
510 * in waiting to serve it. However, if the lease we're
511 * offering is not a free lease, then we may be the only
512 * server that can offer it, so we can't load balance if
513 * the lease isn't in the free or backup state. If it is
514 * in the free or backup state, then that state is what
515 * mandates one server or the other should perform the
516 * allocation, not the LBA...we know the peer cannot
517 * allocate a request for an address in our free state.
519 * So our only compass is lease_mine_to_reallocate(). This
520 * effects both load balancing, and a sanity-check that we
521 * are not going to try to allocate a lease that isn't ours.
523 if ((lease -> binding_state == FTS_FREE ||
524 lease -> binding_state == FTS_BACKUP) &&
525 !lease_mine_to_reallocate (lease)) {
526 log_debug ("%s: lease owned by peer", msgbuf);
527 goto out;
530 /* If the lease is in a transitional state, we can't
531 renew it. */
532 if ((lease -> binding_state == FTS_RELEASED ||
533 lease -> binding_state == FTS_EXPIRED) &&
534 !lease_mine_to_reallocate (lease)) {
535 log_debug ("%s: lease in transition state %s", msgbuf,
536 lease -> binding_state == FTS_RELEASED
537 ? "released" : "expired");
538 goto out;
541 /* It's actually very unlikely that we'll ever get here,
542 but if we do, tell the client to stop using the lease,
543 because the administrator reset it. */
544 if (lease -> binding_state == FTS_RESET &&
545 !lease_mine_to_reallocate (lease)) {
546 log_debug ("%s: lease reset by administrator", msgbuf);
547 nak_lease (packet, &cip);
548 goto out;
551 /* At this point it's possible that we will get a broadcast
552 DHCPREQUEST for a lease that we didn't offer, because
553 both we and the peer are in a position to offer it.
554 In that case, we probably shouldn't answer. In order
555 to not answer, we would have to compare the server
556 identifier sent by the client with the list of possible
557 server identifiers we can send, and if the client's
558 identifier isn't on the list, drop the DHCPREQUEST.
559 We aren't currently doing that for two reasons - first,
560 it's not clear that all clients do the right thing
561 with respect to sending the client identifier, which
562 could mean that we might simply not respond to a client
563 that is depending on us to respond. Secondly, we allow
564 the user to specify the server identifier to send, and
565 we don't enforce that the server identifier should be
566 one of our IP addresses. This is probably not a big
567 deal, but it's theoretically an issue.
569 The reason we care about this is that if both servers
570 send a DHCPACK to the DHCPREQUEST, they are then going
571 to send dueling BNDUPD messages, which could cause
572 trouble. I think it causes no harm, but it seems
573 wrong. */
574 } else
575 peer = (dhcp_failover_state_t *)0;
576 #endif
578 /* If a client on a given network REQUESTs a lease on an
579 address on a different network, NAK it. If the Requested
580 Address option was used, the protocol says that it must
581 have been broadcast, so we can trust the source network
582 information.
584 If ciaddr was specified and Requested Address was not, then
585 we really only know for sure what network a packet came from
586 if it came through a BOOTP gateway - if it came through an
587 IP router, we'll just have to assume that it's cool.
589 If we don't think we know where the packet came from, it
590 came through a gateway from an unknown network, so it's not
591 from a RENEWING client. If we recognize the network it
592 *thinks* it's on, we can NAK it even though we don't
593 recognize the network it's *actually* on; otherwise we just
594 have to ignore it.
596 We don't currently try to take advantage of access to the
597 raw packet, because it's not available on all platforms.
598 So a packet that was unicast to us through a router from a
599 RENEWING client is going to look exactly like a packet that
600 was broadcast to us from an INIT-REBOOT client.
602 Since we can't tell the difference between these two kinds
603 of packets, if the packet appears to have come in off the
604 local wire, we have to treat it as if it's a RENEWING
605 client. This means that we can't NAK a RENEWING client on
606 the local wire that has a bogus address. The good news is
607 that we won't ACK it either, so it should revert to INIT
608 state and send us a DHCPDISCOVER, which we *can* work with.
610 Because we can't detect that a RENEWING client is on the
611 wrong wire, it's going to sit there trying to renew until
612 it gets to the REBIND state, when we *can* NAK it because
613 the packet will get to us through a BOOTP gateway. We
614 shouldn't actually see DHCPREQUEST packets from RENEWING
615 clients on the wrong wire anyway, since their idea of their
616 local router will be wrong. In any case, the protocol
617 doesn't really allow us to NAK a DHCPREQUEST from a
618 RENEWING client, so we can punt on this issue. */
620 if (!packet -> shared_network ||
621 (packet -> raw -> ciaddr.s_addr &&
622 packet -> raw -> giaddr.s_addr) ||
623 (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
625 /* If we don't know where it came from but we do know
626 where it claims to have come from, it didn't come
627 from there. */
628 if (!packet -> shared_network) {
629 if (subnet && subnet -> group -> authoritative) {
630 log_info ("%s: wrong network.", msgbuf);
631 nak_lease (packet, &cip);
632 goto out;
634 /* Otherwise, ignore it. */
635 log_info ("%s: ignored (%s).", msgbuf,
636 (subnet
637 ? "not authoritative" : "unknown subnet"));
638 goto out;
641 /* If we do know where it came from and it asked for an
642 address that is not on that shared network, nak it. */
643 if (subnet)
644 subnet_dereference (&subnet, MDL);
645 if (!find_grouped_subnet (&subnet, packet -> shared_network,
646 cip, MDL)) {
647 if (packet -> shared_network -> group -> authoritative)
649 log_info ("%s: wrong network.", msgbuf);
650 nak_lease (packet, &cip);
651 goto out;
653 log_info ("%s: ignored (not authoritative).", msgbuf);
654 return;
658 /* If the address the client asked for is ours, but it wasn't
659 available for the client, NAK it. */
660 if (!lease && ours) {
661 log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
662 nak_lease (packet, &cip);
663 goto out;
666 /* Otherwise, send the lease to the client if we found one. */
667 if (lease) {
668 ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp,
669 (struct host_decl *)0);
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 if ((oc =
1213 lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
1214 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
1215 (struct client_state *)0,
1216 packet -> options, options,
1217 &global_scope, oc, MDL)) {
1218 /* If there was more than one answer,
1219 take the first. */
1220 if (d1.len >= 4 && d1.data)
1221 memcpy (&raw.siaddr, d1.data, 4);
1222 data_string_forget (&d1, MDL);
1226 /* Set up the option buffer... */
1227 outgoing.packet_length =
1228 cons_options (packet, outgoing.raw, (struct lease *)0,
1229 (struct client_state *)0,
1230 0, packet -> options, options, &global_scope,
1231 0, nulltp, 0,
1232 prl.len ? &prl : (struct data_string *)0,
1233 (char *)0);
1234 option_state_dereference (&options, MDL);
1235 data_string_forget (&prl, MDL);
1237 /* Make sure that the packet is at least as big as a BOOTP packet. */
1238 if (outgoing.packet_length < BOOTP_MIN_LEN)
1239 outgoing.packet_length = BOOTP_MIN_LEN;
1241 raw.giaddr = packet -> raw -> giaddr;
1242 raw.ciaddr = packet -> raw -> ciaddr;
1243 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
1244 raw.hlen = packet -> raw -> hlen;
1245 raw.htype = packet -> raw -> htype;
1247 raw.xid = packet -> raw -> xid;
1248 raw.secs = packet -> raw -> secs;
1249 raw.flags = packet -> raw -> flags;
1250 raw.hops = packet -> raw -> hops;
1251 raw.op = BOOTREPLY;
1253 /* Report what we're sending... */
1254 log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));
1256 #ifdef DEBUG_PACKET
1257 dump_packet (&outgoing);
1258 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
1259 #endif
1261 /* Set up the common stuff... */
1262 to.sin_family = AF_INET;
1263 #ifdef HAVE_SA_LEN
1264 to.sin_len = sizeof to;
1265 #endif
1266 memset (to.sin_zero, 0, sizeof to.sin_zero);
1268 /* Use the IP address we derived for the client. */
1269 memcpy (&to.sin_addr, cip.iabuf, 4);
1270 to.sin_port = remote_port;
1272 errno = 0;
1273 send_packet ((fallback_interface
1274 ? fallback_interface : packet -> interface),
1275 &outgoing, &raw, outgoing.packet_length,
1276 from, &to, (struct hardware *)0);
1277 if (subnet)
1278 subnet_dereference (&subnet, MDL);
1281 void nak_lease (packet, cip)
1282 struct packet *packet;
1283 struct iaddr *cip;
1285 struct sockaddr_in to;
1286 struct in_addr from;
1287 int result;
1288 struct dhcp_packet raw;
1289 unsigned char nak = DHCPNAK;
1290 struct packet outgoing;
1291 struct hardware hto;
1292 unsigned i;
1293 struct data_string data;
1294 struct option_state *options = (struct option_state *)0;
1295 struct expression *expr;
1296 struct option_cache *oc = (struct option_cache *)0;
1297 struct iaddr myfrom;
1299 option_state_allocate (&options, MDL);
1300 memset (&outgoing, 0, sizeof outgoing);
1301 memset (&raw, 0, sizeof raw);
1302 outgoing.raw = &raw;
1304 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
1305 if (!option_cache_allocate (&oc, MDL)) {
1306 log_error ("No memory for DHCPNAK message type.");
1307 option_state_dereference (&options, MDL);
1308 return;
1310 if (!make_const_data (&oc -> expression, &nak, sizeof nak,
1311 0, 0, MDL)) {
1312 log_error ("No memory for expr_const expression.");
1313 option_cache_dereference (&oc, MDL);
1314 option_state_dereference (&options, MDL);
1315 return;
1317 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];
1318 save_option (&dhcp_universe, options, oc);
1319 option_cache_dereference (&oc, MDL);
1321 /* Set DHCP_MESSAGE to whatever the message is */
1322 if (!option_cache_allocate (&oc, MDL)) {
1323 log_error ("No memory for DHCPNAK message type.");
1324 option_state_dereference (&options, MDL);
1325 return;
1327 if (!make_const_data (&oc -> expression,
1328 (unsigned char *)dhcp_message,
1329 strlen (dhcp_message), 1, 0, MDL)) {
1330 log_error ("No memory for expr_const expression.");
1331 option_cache_dereference (&oc, MDL);
1332 option_state_dereference (&options, MDL);
1333 return;
1335 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];
1336 save_option (&dhcp_universe, options, oc);
1337 option_cache_dereference (&oc, MDL);
1339 i = DHO_DHCP_SERVER_IDENTIFIER;
1340 if (!(oc = lookup_option (&dhcp_universe, options, i))) {
1341 use_primary:
1342 oc = (struct option_cache *)0;
1343 if (option_cache_allocate (&oc, MDL)) {
1344 if (make_const_data
1345 (&oc -> expression,
1346 ((unsigned char *)
1347 &packet -> interface -> primary_address),
1348 sizeof packet -> interface -> primary_address,
1349 0, 0, MDL)) {
1350 oc -> option =
1351 dhcp_universe.options [i];
1352 save_option (&dhcp_universe, options, oc);
1354 option_cache_dereference (&oc, MDL);
1356 myfrom.len = sizeof packet -> interface -> primary_address;
1357 memcpy (myfrom.iabuf,
1358 &packet -> interface -> primary_address, myfrom.len);
1359 } else {
1360 memset (&data, 0, sizeof data);
1361 if (evaluate_option_cache (&data, packet, (struct lease *)0,
1362 (struct client_state *)0,
1363 packet -> options, options,
1364 &global_scope, oc, MDL)) {
1365 if (!data.len ||
1366 data.len > sizeof myfrom.iabuf) {
1367 data_string_forget (&data, MDL);
1368 goto use_primary;
1370 memcpy (myfrom.iabuf, data.data, data.len);
1371 myfrom.len = data.len;
1372 data_string_forget (&data, MDL);
1373 } else
1374 goto use_primary;
1377 /* If there were agent options in the incoming packet, return
1378 them. */
1379 if (packet -> raw -> giaddr.s_addr &&
1380 packet -> options -> universe_count > agent_universe.index &&
1381 packet -> options -> universes [agent_universe.index]) {
1382 option_chain_head_reference
1383 ((struct option_chain_head **)
1384 &(options -> universes [agent_universe.index]),
1385 (struct option_chain_head *)
1386 packet -> options -> universes [agent_universe.index],
1387 MDL);
1390 /* Do not use the client's requested parameter list. */
1391 delete_option (&dhcp_universe, packet -> options,
1392 DHO_DHCP_PARAMETER_REQUEST_LIST);
1394 /* Set up the option buffer... */
1395 outgoing.packet_length =
1396 cons_options (packet, outgoing.raw, (struct lease *)0,
1397 (struct client_state *)0,
1398 0, packet -> options, options, &global_scope,
1399 0, 0, 0, (struct data_string *)0, (char *)0);
1400 option_state_dereference (&options, MDL);
1402 /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
1403 raw.siaddr = packet -> interface -> primary_address;
1404 raw.giaddr = packet -> raw -> giaddr;
1405 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
1406 raw.hlen = packet -> raw -> hlen;
1407 raw.htype = packet -> raw -> htype;
1409 raw.xid = packet -> raw -> xid;
1410 raw.secs = packet -> raw -> secs;
1411 raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
1412 raw.hops = packet -> raw -> hops;
1413 raw.op = BOOTREPLY;
1415 /* Report what we're sending... */
1416 log_info ("DHCPNAK on %s to %s via %s",
1417 piaddr (*cip),
1418 print_hw_addr (packet -> raw -> htype,
1419 packet -> raw -> hlen,
1420 packet -> raw -> chaddr),
1421 packet -> raw -> giaddr.s_addr
1422 ? inet_ntoa (packet -> raw -> giaddr)
1423 : packet -> interface -> name);
1427 #ifdef DEBUG_PACKET
1428 dump_packet (packet);
1429 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
1430 dump_packet (&outgoing);
1431 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
1432 #endif
1434 #if 0
1435 hto.hbuf [0] = packet -> raw -> htype;
1436 hto.hlen = packet -> raw -> hlen;
1437 memcpy (&hto.hbuf [1], packet -> raw -> chaddr, hto.hlen);
1438 hto.hlen++;
1439 #endif
1441 /* Set up the common stuff... */
1442 to.sin_family = AF_INET;
1443 #ifdef HAVE_SA_LEN
1444 to.sin_len = sizeof to;
1445 #endif
1446 memset (to.sin_zero, 0, sizeof to.sin_zero);
1448 memcpy (&from, myfrom.iabuf, sizeof from);
1450 /* Make sure that the packet is at least as big as a BOOTP packet. */
1451 if (outgoing.packet_length < BOOTP_MIN_LEN)
1452 outgoing.packet_length = BOOTP_MIN_LEN;
1454 /* If this was gatewayed, send it back to the gateway.
1455 Otherwise, broadcast it on the local network. */
1456 if (raw.giaddr.s_addr) {
1457 to.sin_addr = raw.giaddr;
1458 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
1459 to.sin_port = local_port;
1460 else
1461 to.sin_port = remote_port; /* for testing. */
1463 if (fallback_interface) {
1464 result = send_packet (fallback_interface,
1465 packet, &raw,
1466 outgoing.packet_length,
1467 from, &to, &hto);
1468 return;
1470 } else {
1471 to.sin_addr = limited_broadcast;
1472 to.sin_port = remote_port;
1475 errno = 0;
1476 result = send_packet (packet -> interface,
1477 packet, &raw, outgoing.packet_length,
1478 from, &to, (struct hardware *)0);
1481 void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
1482 struct packet *packet;
1483 struct lease *lease;
1484 unsigned int offer;
1485 TIME when;
1486 char *msg;
1487 int ms_nulltp;
1488 struct host_decl *hp;
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 (hp)
1518 host_reference (&host, hp, MDL);
1519 else if (lease -> host)
1520 host_reference (&host, lease -> host, MDL);
1522 /* Allocate a lease state structure... */
1523 state = new_lease_state (MDL);
1524 if (!state)
1525 log_fatal ("unable to allocate lease state!");
1526 state -> got_requested_address = packet -> got_requested_address;
1527 shared_network_reference (&state -> shared_network,
1528 packet -> interface -> shared_network, MDL);
1530 /* See if we got a server identifier option. */
1531 if (lookup_option (&dhcp_universe,
1532 packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
1533 state -> got_server_identifier = 1;
1535 /* If there were agent options in the incoming packet, return
1536 them. Do not return the agent options if they were stashed
1537 on the lease. */
1538 if (packet -> raw -> giaddr.s_addr &&
1539 packet -> options -> universe_count > agent_universe.index &&
1540 packet -> options -> universes [agent_universe.index] &&
1541 (state -> options -> universe_count <= agent_universe.index ||
1542 !state -> options -> universes [agent_universe.index]) &&
1543 lease -> agent_options !=
1544 ((struct option_chain_head *)
1545 packet -> options -> universes [agent_universe.index])) {
1546 option_chain_head_reference
1547 ((struct option_chain_head **)
1548 &(state -> options -> universes [agent_universe.index]),
1549 (struct option_chain_head *)
1550 packet -> options -> universes [agent_universe.index],
1551 MDL);
1554 /* If we are offering a lease that is still currently valid, preserve
1555 the events. We need to do this because if the client does not
1556 REQUEST our offer, it will expire in 2 minutes, overriding the
1557 expire time in the currently in force lease. We want the expire
1558 events to be executed at that point. */
1559 if (lease -> ends <= cur_time && offer != DHCPOFFER) {
1560 /* Get rid of any old expiry or release statements - by
1561 executing the statements below, we will be inserting new
1562 ones if there are any to insert. */
1563 if (lease -> on_expiry)
1564 executable_statement_dereference (&lease -> on_expiry,
1565 MDL);
1566 if (lease -> on_commit)
1567 executable_statement_dereference (&lease -> on_commit,
1568 MDL);
1569 if (lease -> on_release)
1570 executable_statement_dereference (&lease -> on_release,
1571 MDL);
1574 /* Execute statements in scope starting with the subnet scope. */
1575 execute_statements_in_scope ((struct binding_value **)0,
1576 packet, lease, (struct client_state *)0,
1577 packet -> options,
1578 state -> options, &lease -> scope,
1579 lease -> subnet -> group,
1580 (struct group *)0);
1582 /* If the lease is from a pool, run the pool scope. */
1583 if (lease -> pool)
1584 (execute_statements_in_scope
1585 ((struct binding_value **)0, packet, lease,
1586 (struct client_state *)0, packet -> options,
1587 state -> options, &lease -> scope, lease -> pool -> group,
1588 lease -> pool -> shared_network -> group));
1590 /* Execute statements from class scopes. */
1591 for (i = packet -> class_count; i > 0; i--) {
1592 execute_statements_in_scope
1593 ((struct binding_value **)0,
1594 packet, lease, (struct client_state *)0,
1595 packet -> options, state -> options,
1596 &lease -> scope, packet -> classes [i - 1] -> group,
1597 (lease -> pool
1598 ? lease -> pool -> group
1599 : lease -> subnet -> group));
1602 /* See if the client is only supposed to have one lease at a time,
1603 and if so, find its other leases and release them. We can only
1604 do this on DHCPREQUEST. It's a little weird to do this before
1605 looking at permissions, because the client might not actually
1606 _get_ a lease after we've done the permission check, but the
1607 assumption for this option is that the client has exactly one
1608 network interface, and will only ever remember one lease. So
1609 if it sends a DHCPREQUEST, and doesn't get the lease, it's already
1610 forgotten about its old lease, so we can too. */
1611 if (packet -> packet_type == DHCPREQUEST &&
1612 (oc = lookup_option (&server_universe, state -> options,
1613 SV_ONE_LEASE_PER_CLIENT)) &&
1614 evaluate_boolean_option_cache (&ignorep,
1615 packet, lease,
1616 (struct client_state *)0,
1617 packet -> options,
1618 state -> options, &lease -> scope,
1619 oc, MDL)) {
1620 struct lease *seek;
1621 if (lease -> uid_len) {
1622 do {
1623 seek = (struct lease *)0;
1624 find_lease_by_uid (&seek, lease -> uid,
1625 lease -> uid_len, MDL);
1626 if (!seek)
1627 break;
1628 if (seek == lease && !seek -> n_uid) {
1629 lease_dereference (&seek, MDL);
1630 break;
1632 next = (struct lease *)0;
1634 /* Don't release expired leases, and don't
1635 release the lease we're going to assign. */
1636 next = (struct lease *)0;
1637 while (seek) {
1638 if (seek -> n_uid)
1639 lease_reference (&next, seek -> n_uid, MDL);
1640 if (seek != lease &&
1641 seek -> binding_state != FTS_RELEASED &&
1642 seek -> binding_state != FTS_EXPIRED &&
1643 seek -> binding_state != FTS_RESET &&
1644 seek -> binding_state != FTS_FREE &&
1645 seek -> binding_state != FTS_BACKUP)
1646 break;
1647 lease_dereference (&seek, MDL);
1648 if (next) {
1649 lease_reference (&seek, next, MDL);
1650 lease_dereference (&next, MDL);
1653 if (next)
1654 lease_dereference (&next, MDL);
1655 if (seek) {
1656 release_lease (seek, packet);
1657 lease_dereference (&seek, MDL);
1658 } else
1659 break;
1660 } while (1);
1662 if (!lease -> uid_len ||
1663 (host &&
1664 !host -> client_identifier.len &&
1665 (oc = lookup_option (&server_universe, state -> options,
1666 SV_DUPLICATES)) &&
1667 !evaluate_boolean_option_cache (&ignorep, packet, lease,
1668 (struct client_state *)0,
1669 packet -> options,
1670 state -> options,
1671 &lease -> scope,
1672 oc, MDL))) {
1673 do {
1674 seek = (struct lease *)0;
1675 find_lease_by_hw_addr
1676 (&seek, lease -> hardware_addr.hbuf,
1677 lease -> hardware_addr.hlen, MDL);
1678 if (!seek)
1679 break;
1680 if (seek == lease && !seek -> n_hw) {
1681 lease_dereference (&seek, MDL);
1682 break;
1684 next = (struct lease *)0;
1685 while (seek) {
1686 if (seek -> n_hw)
1687 lease_reference (&next, seek -> n_hw, MDL);
1688 if (seek != lease &&
1689 seek -> binding_state != FTS_RELEASED &&
1690 seek -> binding_state != FTS_EXPIRED &&
1691 seek -> binding_state != FTS_RESET &&
1692 seek -> binding_state != FTS_FREE &&
1693 seek -> binding_state != FTS_BACKUP)
1694 break;
1695 lease_dereference (&seek, MDL);
1696 if (next) {
1697 lease_reference (&seek, next, MDL);
1698 lease_dereference (&next, MDL);
1701 if (next)
1702 lease_dereference (&next, MDL);
1703 if (seek) {
1704 release_lease (seek, packet);
1705 lease_dereference (&seek, MDL);
1706 } else
1707 break;
1708 } while (1);
1713 /* Make sure this packet satisfies the configured minimum
1714 number of seconds. */
1715 memset (&d1, 0, sizeof d1);
1716 if (offer == DHCPOFFER &&
1717 (oc = lookup_option (&server_universe, state -> options,
1718 SV_MIN_SECS))) {
1719 if (evaluate_option_cache (&d1, packet, lease,
1720 (struct client_state *)0,
1721 packet -> options, state -> options,
1722 &lease -> scope, oc, MDL)) {
1723 if (d1.len &&
1724 ntohs (packet -> raw -> secs) < d1.data [0]) {
1725 log_info ("%s: %d secs < %d", msg,
1726 ntohs (packet -> raw -> secs),
1727 d1.data [0]);
1728 data_string_forget (&d1, MDL);
1729 free_lease_state (state, MDL);
1730 if (host)
1731 host_dereference (&host, MDL);
1732 return;
1734 data_string_forget (&d1, MDL);
1738 /* Try to find a matching host declaration for this lease.
1740 if (!host) {
1741 struct host_decl *hp = (struct host_decl *)0;
1742 struct host_decl *h;
1744 /* Try to find a host_decl that matches the client
1745 identifier or hardware address on the packet, and
1746 has no fixed IP address. If there is one, hang
1747 it off the lease so that its option definitions
1748 can be used. */
1749 oc = lookup_option (&dhcp_universe, packet -> options,
1750 DHO_DHCP_CLIENT_IDENTIFIER);
1751 if (oc &&
1752 evaluate_option_cache (&d1, packet, lease,
1753 (struct client_state *)0,
1754 packet -> options, state -> options,
1755 &lease -> scope, oc, MDL)) {
1756 find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
1757 data_string_forget (&d1, MDL);
1758 for (h = hp; h; h = h -> n_ipaddr) {
1759 if (!h -> fixed_addr)
1760 break;
1762 if (h)
1763 host_reference (&host, h, MDL);
1765 if (!host) {
1766 find_hosts_by_haddr (&hp,
1767 packet -> raw -> htype,
1768 packet -> raw -> chaddr,
1769 packet -> raw -> hlen,
1770 MDL);
1771 for (h = hp; h; h = h -> n_ipaddr) {
1772 if (!h -> fixed_addr)
1773 break;
1775 if (h)
1776 host_reference (&host, h, MDL);
1778 if (hp)
1779 host_dereference (&hp, MDL);
1782 /* If we have a host_decl structure, run the options associated
1783 with its group. Wether the host decl struct is old or not. */
1784 if (host)
1785 execute_statements_in_scope ((struct binding_value **)0,
1786 packet, lease,
1787 (struct client_state *)0,
1788 packet -> options,
1789 state -> options, &lease -> scope,
1790 host -> group,
1791 (lease -> pool
1792 ? lease -> pool -> group
1793 : lease -> subnet -> group));
1795 /* Drop the request if it's not allowed for this client. By
1796 default, unknown clients are allowed. */
1797 if (!host &&
1798 (oc = lookup_option (&server_universe, state -> options,
1799 SV_BOOT_UNKNOWN_CLIENTS)) &&
1800 !evaluate_boolean_option_cache (&ignorep,
1801 packet, lease,
1802 (struct client_state *)0,
1803 packet -> options,
1804 state -> options,
1805 &lease -> scope, oc, MDL)) {
1806 if (!ignorep)
1807 log_info ("%s: unknown client", msg);
1808 free_lease_state (state, MDL);
1809 if (host)
1810 host_dereference (&host, MDL);
1811 return;
1814 /* Drop the request if it's not allowed for this client. */
1815 if (!offer &&
1816 (oc = lookup_option (&server_universe, state -> options,
1817 SV_ALLOW_BOOTP)) &&
1818 !evaluate_boolean_option_cache (&ignorep,
1819 packet, lease,
1820 (struct client_state *)0,
1821 packet -> options,
1822 state -> options,
1823 &lease -> scope, oc, MDL)) {
1824 if (!ignorep)
1825 log_info ("%s: bootp disallowed", msg);
1826 free_lease_state (state, MDL);
1827 if (host)
1828 host_dereference (&host, MDL);
1829 return;
1832 /* Drop the request if booting is specifically denied. */
1833 oc = lookup_option (&server_universe, state -> options,
1834 SV_ALLOW_BOOTING);
1835 if (oc &&
1836 !evaluate_boolean_option_cache (&ignorep,
1837 packet, lease,
1838 (struct client_state *)0,
1839 packet -> options,
1840 state -> options,
1841 &lease -> scope, oc, MDL)) {
1842 if (!ignorep)
1843 log_info ("%s: booting disallowed", msg);
1844 free_lease_state (state, MDL);
1845 if (host)
1846 host_dereference (&host, MDL);
1847 return;
1850 /* If we are configured to do per-class billing, do it. */
1851 if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
1852 /* See if the lease is currently being billed to a
1853 class, and if so, whether or not it can continue to
1854 be billed to that class. */
1855 if (lease -> billing_class) {
1856 for (i = 0; i < packet -> class_count; i++)
1857 if (packet -> classes [i] ==
1858 lease -> billing_class)
1859 break;
1860 if (i == packet -> class_count)
1861 unbill_class (lease, lease -> billing_class);
1864 /* If we don't have an active billing, see if we need
1865 one, and if we do, try to do so. */
1866 if (!lease -> billing_class) {
1867 for (i = 0; i < packet -> class_count; i++) {
1868 if (packet -> classes [i] -> lease_limit)
1869 break;
1871 if (i != packet -> class_count) {
1872 for (i = 0; i < packet -> class_count; i++)
1873 if ((packet ->
1874 classes [i] -> lease_limit) &&
1875 bill_class (lease,
1876 packet -> classes [i]))
1877 break;
1878 if (i == packet -> class_count) {
1879 log_info ("%s: no available billing",
1880 msg);
1881 free_lease_state (state, MDL);
1882 if (host)
1883 host_dereference (&host, MDL);
1884 /* XXX possibly not necessary: */
1885 return;
1891 /* Figure out the filename. */
1892 oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
1893 if (oc)
1894 evaluate_option_cache (&state -> filename, packet, lease,
1895 (struct client_state *)0,
1896 packet -> options, state -> options,
1897 &lease -> scope, oc, MDL);
1899 /* Choose a server name as above. */
1900 oc = lookup_option (&server_universe, state -> options,
1901 SV_SERVER_NAME);
1902 if (oc)
1903 evaluate_option_cache (&state -> server_name, packet, lease,
1904 (struct client_state *)0,
1905 packet -> options, state -> options,
1906 &lease -> scope, oc, MDL);
1908 /* At this point, we have a lease that we can offer the client.
1909 Now we construct a lease structure that contains what we want,
1910 and call supersede_lease to do the right thing with it. */
1911 lt = (struct lease *)0;
1912 result = lease_allocate (&lt, MDL);
1913 if (result != ISC_R_SUCCESS) {
1914 log_info ("%s: can't allocate temporary lease structure: %s",
1915 msg, isc_result_totext (result));
1916 free_lease_state (state, MDL);
1917 if (host)
1918 host_dereference (&host, MDL);
1919 return;
1922 /* Use the ip address of the lease that we finally found in
1923 the database. */
1924 lt -> ip_addr = lease -> ip_addr;
1926 /* Start now. */
1927 lt -> starts = cur_time;
1929 /* Figure out how long a lease to assign. If this is a
1930 dynamic BOOTP lease, its duration must be infinite. */
1931 if (offer) {
1932 default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
1933 if ((oc = lookup_option (&server_universe, state -> options,
1934 SV_DEFAULT_LEASE_TIME))) {
1935 if (evaluate_option_cache (&d1, packet, lease,
1936 (struct client_state *)0,
1937 packet -> options,
1938 state -> options,
1939 &lease -> scope, oc, MDL)) {
1940 if (d1.len == sizeof (u_int32_t))
1941 default_lease_time =
1942 getULong (d1.data);
1943 data_string_forget (&d1, MDL);
1947 if ((oc = lookup_option (&dhcp_universe, packet -> options,
1948 DHO_DHCP_LEASE_TIME)))
1949 s1 = evaluate_option_cache (&d1, packet, lease,
1950 (struct client_state *)0,
1951 packet -> options,
1952 state -> options,
1953 &lease -> scope, oc, MDL);
1954 else
1955 s1 = 0;
1957 if (s1 && d1.len == sizeof (u_int32_t)) {
1958 lease_time = getULong (d1.data);
1959 data_string_forget (&d1, MDL);
1960 } else {
1961 if (s1)
1962 data_string_forget (&d1, MDL);
1963 lease_time = default_lease_time;
1966 /* See if there's a maximum lease time. */
1967 max_lease_time = DEFAULT_MAX_LEASE_TIME;
1968 if ((oc = lookup_option (&server_universe, state -> options,
1969 SV_MAX_LEASE_TIME))) {
1970 if (evaluate_option_cache (&d1, packet, lease,
1971 (struct client_state *)0,
1972 packet -> options,
1973 state -> options,
1974 &lease -> scope, oc, MDL)) {
1975 if (d1.len == sizeof (u_int32_t))
1976 max_lease_time =
1977 getULong (d1.data);
1978 data_string_forget (&d1, MDL);
1982 /* Enforce the maximum lease length. */
1983 if (lease_time < 0 /* XXX */
1984 || lease_time > max_lease_time)
1985 lease_time = max_lease_time;
1987 min_lease_time = DEFAULT_MIN_LEASE_TIME;
1988 if (min_lease_time > max_lease_time)
1989 min_lease_time = max_lease_time;
1991 if ((oc = lookup_option (&server_universe, state -> options,
1992 SV_MIN_LEASE_TIME))) {
1993 if (evaluate_option_cache (&d1, packet, lease,
1994 (struct client_state *)0,
1995 packet -> options,
1996 state -> options,
1997 &lease -> scope, oc, MDL)) {
1998 if (d1.len == sizeof (u_int32_t))
1999 min_lease_time = getULong (d1.data);
2000 data_string_forget (&d1, MDL);
2004 if (lease_time < min_lease_time) {
2005 if (min_lease_time)
2006 lease_time = min_lease_time;
2007 else
2008 lease_time = default_lease_time;
2011 #if defined (FAILOVER_PROTOCOL)
2012 /* Okay, we know the lease duration. Now check the
2013 failover state, if any. */
2014 if (lease -> tsfp) {
2015 lt ->tsfp = lease ->tsfp;
2017 if (lease -> pool && lease -> pool -> failover_peer) {
2018 dhcp_failover_state_t *peer =
2019 lease -> pool -> failover_peer;
2021 /* If the lease time we arrived at exceeds what
2022 the peer has, we can only issue a lease of
2023 peer -> mclt, but we can tell the peer we
2024 want something longer in the future. */
2025 /* XXX This may result in updates that only push
2026 XXX the peer's expiry time for this lease up
2027 XXX by a few seconds - think about this again
2028 XXX later. */
2029 if (lease_time > peer -> mclt &&
2030 cur_time + lease_time > lease -> tsfp) {
2031 /* Here we're assuming that if we don't have
2032 to update tstp, there's already an update
2033 queued. May want to revisit this. */
2034 if (peer -> me.state != partner_down &&
2035 cur_time + lease_time > lease -> tstp)
2036 lt -> tstp = (cur_time + lease_time +
2037 peer -> mclt / 2);
2039 /* Now choose a lease time that is either
2040 MCLT, for a lease that's never before been
2041 assigned, or TSFP + MCLT for a lease that
2042 has.
2043 XXX Note that TSFP may be < cur_time.
2044 XXX What do we do in this case?
2045 XXX should the expiry timer on the lease
2046 XXX set tsfp and tstp to zero? */
2047 if (lease -> tsfp < cur_time) {
2048 lease_time = peer -> mclt;
2049 } else {
2050 lease_time = (lease -> tsfp - cur_time
2051 + peer -> mclt);
2053 } else {
2054 if (cur_time + lease_time > lease -> tsfp &&
2055 lease_time > peer -> mclt / 2) {
2056 lt -> tstp = (cur_time + lease_time +
2057 peer -> mclt / 2);
2058 } else {
2059 lt -> tstp = (cur_time + lease_time +
2060 lease_time / 2);
2064 lt -> cltt = cur_time;
2066 #endif /* FAILOVER_PROTOCOL */
2068 /* If the lease duration causes the time value to wrap,
2069 use the maximum expiry time. */
2070 if (cur_time + lease_time < cur_time)
2071 state -> offered_expiry = MAX_TIME - 1;
2072 else
2073 state -> offered_expiry = cur_time + lease_time;
2074 if (when)
2075 lt -> ends = when;
2076 else
2077 lt -> ends = state -> offered_expiry;
2079 /* Don't make lease active until we actually get a
2080 DHCPREQUEST. */
2081 if (offer == DHCPACK)
2082 lt -> next_binding_state = FTS_ACTIVE;
2083 else
2084 lt -> next_binding_state = lease -> binding_state;
2085 } else {
2086 lease_time = MAX_TIME - cur_time;
2088 if ((oc = lookup_option (&server_universe, state -> options,
2089 SV_BOOTP_LEASE_LENGTH))) {
2090 if (evaluate_option_cache (&d1, packet, lease,
2091 (struct client_state *)0,
2092 packet -> options,
2093 state -> options,
2094 &lease -> scope, oc, MDL)) {
2095 if (d1.len == sizeof (u_int32_t))
2096 lease_time = getULong (d1.data);
2097 data_string_forget (&d1, MDL);
2101 if ((oc = lookup_option (&server_universe, state -> options,
2102 SV_BOOTP_LEASE_CUTOFF))) {
2103 if (evaluate_option_cache (&d1, packet, lease,
2104 (struct client_state *)0,
2105 packet -> options,
2106 state -> options,
2107 &lease -> scope, oc, MDL)) {
2108 if (d1.len == sizeof (u_int32_t))
2109 lease_time = (getULong (d1.data) -
2110 cur_time);
2111 data_string_forget (&d1, MDL);
2115 lt -> ends = state -> offered_expiry = cur_time + lease_time;
2116 lt -> next_binding_state = FTS_ACTIVE;
2119 lt -> timestamp = cur_time;
2121 /* Record the uid, if given... */
2122 oc = lookup_option (&dhcp_universe, packet -> options,
2123 DHO_DHCP_CLIENT_IDENTIFIER);
2124 if (oc &&
2125 evaluate_option_cache (&d1, packet, lease,
2126 (struct client_state *)0,
2127 packet -> options, state -> options,
2128 &lease -> scope, oc, MDL)) {
2129 if (d1.len <= sizeof lt -> uid_buf) {
2130 memcpy (lt -> uid_buf, d1.data, d1.len);
2131 lt -> uid = lt -> uid_buf;
2132 lt -> uid_max = sizeof lt -> uid_buf;
2133 lt -> uid_len = d1.len;
2134 } else {
2135 unsigned char *tuid;
2136 lt -> uid_max = d1.len;
2137 lt -> uid_len = d1.len;
2138 tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);
2139 /* XXX inelegant */
2140 if (!tuid)
2141 log_fatal ("no memory for large uid.");
2142 memcpy (tuid, d1.data, lt -> uid_len);
2143 lt -> uid = tuid;
2145 data_string_forget (&d1, MDL);
2148 if (host) {
2149 host_reference (&lt -> host, host, MDL);
2150 host_dereference (&host, MDL);
2152 if (lease -> subnet)
2153 subnet_reference (&lt -> subnet, lease -> subnet, MDL);
2154 if (lease -> billing_class)
2155 class_reference (&lt -> billing_class,
2156 lease -> billing_class, MDL);
2158 /* Set a flag if this client is a broken client that NUL
2159 terminates string options and expects us to do likewise. */
2160 if (ms_nulltp)
2161 lease -> flags |= MS_NULL_TERMINATION;
2162 else
2163 lease -> flags &= ~MS_NULL_TERMINATION;
2165 /* Save any bindings. */
2166 if (lease -> scope) {
2167 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
2168 binding_scope_dereference (&lease -> scope, MDL);
2170 if (lease -> agent_options)
2171 option_chain_head_reference (&lt -> agent_options,
2172 lease -> agent_options, MDL);
2174 /* If we got relay agent information options, and the packet really
2175 looks like it came through a relay agent, and if this feature is
2176 not disabled, save the relay agent information options that came
2177 in with the packet, so that we can use them at renewal time when
2178 the packet won't have gone through a relay agent. */
2179 if (packet -> raw -> giaddr.s_addr &&
2180 packet -> options -> universe_count > agent_universe.index &&
2181 packet -> options -> universes [agent_universe.index] &&
2182 (state -> options -> universe_count <= agent_universe.index ||
2183 state -> options -> universes [agent_universe.index] ==
2184 packet -> options -> universes [agent_universe.index])) {
2185 oc = lookup_option (&server_universe, state -> options,
2186 SV_STASH_AGENT_OPTIONS);
2187 if (!oc ||
2188 evaluate_boolean_option_cache (&ignorep, packet, lease,
2189 (struct client_state *)0,
2190 packet -> options,
2191 state -> options,
2192 &lease -> scope, oc, MDL)) {
2193 if (lt -> agent_options)
2194 option_chain_head_dereference (&lt -> agent_options, MDL);
2195 option_chain_head_reference
2196 (&lt -> agent_options,
2197 (struct option_chain_head *)
2198 packet -> options -> universes [agent_universe.index],
2199 MDL);
2203 /* Replace the old lease hostname with the new one, if it's changed. */
2204 oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
2205 if (oc)
2206 s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
2207 (struct client_state *)0,
2208 packet -> options,
2209 (struct option_state *)0,
2210 &global_scope, oc, MDL);
2211 else
2212 s1 = 0;
2214 if (oc && s1 &&
2215 lease -> client_hostname &&
2216 strlen (lease -> client_hostname) == d1.len &&
2217 !memcmp (lease -> client_hostname, d1.data, d1.len)) {
2218 /* Hasn't changed. */
2219 data_string_forget (&d1, MDL);
2220 lt -> client_hostname = lease -> client_hostname;
2221 lease -> client_hostname = (char *)0;
2222 } else if (oc && s1) {
2223 lt -> client_hostname = dmalloc (d1.len + 1, MDL);
2224 if (!lt -> client_hostname)
2225 log_error ("no memory for client hostname.");
2226 else {
2227 memcpy (lt -> client_hostname, d1.data, d1.len);
2228 lt -> client_hostname [d1.len] = 0;
2230 data_string_forget (&d1, MDL);
2233 /* Record the hardware address, if given... */
2234 lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
2235 lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
2236 memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
2237 sizeof packet -> raw -> chaddr);
2239 lt -> flags = lease -> flags & ~PERSISTENT_FLAGS;
2241 /* If there are statements to execute when the lease is
2242 committed, execute them. */
2243 if (lease -> on_commit && (!offer || offer == DHCPACK)) {
2244 execute_statements ((struct binding_value **)0,
2245 packet, lt, (struct client_state *)0,
2246 packet -> options,
2247 state -> options, &lt -> scope,
2248 lease -> on_commit);
2249 if (lease -> on_commit)
2250 executable_statement_dereference (&lease -> on_commit,
2251 MDL);
2254 #ifdef NSUPDATE
2255 /* Perform DDNS updates, if configured to. */
2256 if ((!offer || offer == DHCPACK) &&
2257 (!(oc = lookup_option (&server_universe, state -> options,
2258 SV_DDNS_UPDATES)) ||
2259 evaluate_boolean_option_cache (&ignorep, packet, lt,
2260 (struct client_state *)0,
2261 packet -> options,
2262 state -> options,
2263 &lt -> scope, oc, MDL))) {
2264 ddns_updates (packet, lt, lease, state);
2266 #endif /* NSUPDATE */
2268 /* Don't call supersede_lease on a mocked-up lease. */
2269 if (lease -> flags & STATIC_LEASE) {
2270 /* Copy the hardware address into the static lease
2271 structure. */
2272 lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
2273 lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
2274 memcpy (&lease -> hardware_addr.hbuf [1],
2275 packet -> raw -> chaddr,
2276 sizeof packet -> raw -> chaddr); /* XXX */
2277 } else {
2278 /* Install the new information about this lease in the
2279 database. If this is a DHCPACK or a dynamic BOOTREPLY
2280 and we can't write the lease, don't ACK it (or BOOTREPLY
2281 it) either. */
2283 if (!supersede_lease (lease, lt, !offer || offer == DHCPACK,
2284 offer == DHCPACK, offer == DHCPACK)) {
2285 log_info ("%s: database update failed", msg);
2286 free_lease_state (state, MDL);
2287 lease_dereference (&lt, MDL);
2288 return;
2291 lease_dereference (&lt, MDL);
2293 /* Remember the interface on which the packet arrived. */
2294 state -> ip = packet -> interface;
2296 /* Remember the giaddr, xid, secs, flags and hops. */
2297 state -> giaddr = packet -> raw -> giaddr;
2298 state -> ciaddr = packet -> raw -> ciaddr;
2299 state -> xid = packet -> raw -> xid;
2300 state -> secs = packet -> raw -> secs;
2301 state -> bootp_flags = packet -> raw -> flags;
2302 state -> hops = packet -> raw -> hops;
2303 state -> offer = offer;
2305 /* If we're always supposed to broadcast to this client, set
2306 the broadcast bit in the bootp flags field. */
2307 if ((oc = lookup_option (&server_universe, state -> options,
2308 SV_ALWAYS_BROADCAST)) &&
2309 evaluate_boolean_option_cache (&ignorep, packet, lease,
2310 (struct client_state *)0,
2311 packet -> options, state -> options,
2312 &lease -> scope, oc, MDL))
2313 state -> bootp_flags |= htons (BOOTP_BROADCAST);
2315 /* Get the Maximum Message Size option from the packet, if one
2316 was sent. */
2317 oc = lookup_option (&dhcp_universe, packet -> options,
2318 DHO_DHCP_MAX_MESSAGE_SIZE);
2319 if (oc &&
2320 evaluate_option_cache (&d1, packet, lease,
2321 (struct client_state *)0,
2322 packet -> options, state -> options,
2323 &lease -> scope, oc, MDL)) {
2324 if (d1.len == sizeof (u_int16_t))
2325 state -> max_message_size = getUShort (d1.data);
2326 data_string_forget (&d1, MDL);
2327 } else {
2328 oc = lookup_option (&dhcp_universe, state -> options,
2329 DHO_DHCP_MAX_MESSAGE_SIZE);
2330 if (oc &&
2331 evaluate_option_cache (&d1, packet, lease,
2332 (struct client_state *)0,
2333 packet -> options, state -> options,
2334 &lease -> scope, oc, MDL)) {
2335 if (d1.len == sizeof (u_int16_t))
2336 state -> max_message_size =
2337 getUShort (d1.data);
2338 data_string_forget (&d1, MDL);
2342 /* Get the Subnet Selection option from the packet, if one
2343 was sent. */
2344 if ((oc = lookup_option (&dhcp_universe, packet -> options,
2345 DHO_SUBNET_SELECTION))) {
2347 /* Make a copy of the data. */
2348 struct option_cache *noc = (struct option_cache *)0;
2349 if (option_cache_allocate (&noc, MDL)) {
2350 if (oc -> data.len)
2351 data_string_copy (&noc -> data,
2352 &oc -> data, MDL);
2353 if (oc -> expression)
2354 expression_reference (&noc -> expression,
2355 oc -> expression, MDL);
2356 if (oc -> option)
2357 noc -> option = oc -> option;
2360 save_option (&dhcp_universe, state -> options, noc);
2361 option_cache_dereference (&noc, MDL);
2364 /* Now, if appropriate, put in DHCP-specific options that
2365 override those. */
2366 if (state -> offer) {
2367 i = DHO_DHCP_MESSAGE_TYPE;
2368 oc = (struct option_cache *)0;
2369 if (option_cache_allocate (&oc, MDL)) {
2370 if (make_const_data (&oc -> expression,
2371 &state -> offer, 1, 0, 0, MDL)) {
2372 oc -> option =
2373 dhcp_universe.options [i];
2374 save_option (&dhcp_universe,
2375 state -> options, oc);
2377 option_cache_dereference (&oc, MDL);
2379 i = DHO_DHCP_SERVER_IDENTIFIER;
2380 if (!(oc = lookup_option (&dhcp_universe,
2381 state -> options, i))) {
2382 use_primary:
2383 oc = (struct option_cache *)0;
2384 if (option_cache_allocate (&oc, MDL)) {
2385 if (make_const_data
2386 (&oc -> expression,
2387 ((unsigned char *)
2388 &state -> ip -> primary_address),
2389 sizeof state -> ip -> primary_address,
2390 0, 0, MDL)) {
2391 oc -> option =
2392 dhcp_universe.options [i];
2393 save_option (&dhcp_universe,
2394 state -> options, oc);
2396 option_cache_dereference (&oc, MDL);
2398 state -> from.len =
2399 sizeof state -> ip -> primary_address;
2400 memcpy (state -> from.iabuf,
2401 &state -> ip -> primary_address,
2402 state -> from.len);
2403 } else {
2404 if (evaluate_option_cache (&d1, packet, lease,
2405 (struct client_state *)0,
2406 packet -> options,
2407 state -> options,
2408 &lease -> scope, oc, MDL)) {
2409 if (!d1.len ||
2410 d1.len > sizeof state -> from.iabuf) {
2411 data_string_forget (&d1, MDL);
2412 goto use_primary;
2414 memcpy (state -> from.iabuf, d1.data, d1.len);
2415 state -> from.len = d1.len;
2416 data_string_forget (&d1, MDL);
2417 } else
2418 goto use_primary;
2421 offered_lease_time =
2422 state -> offered_expiry - cur_time;
2424 putULong ((unsigned char *)&state -> expiry,
2425 (unsigned long)offered_lease_time);
2426 i = DHO_DHCP_LEASE_TIME;
2427 if (lookup_option (&dhcp_universe, state -> options, i))
2428 log_error ("dhcp-lease-time option for %s overridden.",
2429 inet_ntoa (state -> ciaddr));
2430 oc = (struct option_cache *)0;
2431 if (option_cache_allocate (&oc, MDL)) {
2432 if (make_const_data (&oc -> expression,
2433 (unsigned char *)&state -> expiry,
2434 sizeof state -> expiry,
2435 0, 0, MDL)) {
2436 oc -> option = dhcp_universe.options [i];
2437 save_option (&dhcp_universe,
2438 state -> options, oc);
2440 option_cache_dereference (&oc, MDL);
2443 /* Renewal time is lease time * 0.5. */
2444 offered_lease_time /= 2;
2445 putULong ((unsigned char *)&state -> renewal,
2446 (unsigned long)offered_lease_time);
2447 i = DHO_DHCP_RENEWAL_TIME;
2448 if (lookup_option (&dhcp_universe, state -> options, i))
2449 log_error ("overriding dhcp-renewal-time for %s.",
2450 inet_ntoa (state -> ciaddr));
2451 oc = (struct option_cache *)0;
2452 if (option_cache_allocate (&oc, MDL)) {
2453 if (make_const_data (&oc -> expression,
2454 (unsigned char *)
2455 &state -> renewal,
2456 sizeof state -> renewal,
2457 0, 0, MDL)) {
2458 oc -> option = dhcp_universe.options [i];
2459 save_option (&dhcp_universe,
2460 state -> options, oc);
2462 option_cache_dereference (&oc, MDL);
2465 /* Rebinding time is lease time * 0.875. */
2466 offered_lease_time += (offered_lease_time / 2
2467 + offered_lease_time / 4);
2468 putULong ((unsigned char *)&state -> rebind,
2469 (unsigned)offered_lease_time);
2470 i = DHO_DHCP_REBINDING_TIME;
2471 if (lookup_option (&dhcp_universe, state -> options, i))
2472 log_error ("overriding dhcp-rebinding-time for %s.",
2473 inet_ntoa (state -> ciaddr));
2474 oc = (struct option_cache *)0;
2475 if (option_cache_allocate (&oc, MDL)) {
2476 if (make_const_data (&oc -> expression,
2477 (unsigned char *)&state -> rebind,
2478 sizeof state -> rebind,
2479 0, 0, MDL)) {
2480 oc -> option = dhcp_universe.options [i];
2481 save_option (&dhcp_universe,
2482 state -> options, oc);
2484 option_cache_dereference (&oc, MDL);
2486 } else {
2487 state -> from.len =
2488 sizeof state -> ip -> primary_address;
2489 memcpy (state -> from.iabuf,
2490 &state -> ip -> primary_address,
2491 state -> from.len);
2494 /* Figure out the address of the boot file server. */
2495 memset (&state -> siaddr, 0, sizeof state -> siaddr);
2496 if ((oc =
2497 lookup_option (&server_universe,
2498 state -> options, SV_NEXT_SERVER))) {
2499 if (evaluate_option_cache (&d1, packet, lease,
2500 (struct client_state *)0,
2501 packet -> options, state -> options,
2502 &lease -> scope, oc, MDL)) {
2503 /* If there was more than one answer,
2504 take the first. */
2505 if (d1.len >= 4 && d1.data)
2506 memcpy (&state -> siaddr, d1.data, 4);
2507 data_string_forget (&d1, MDL);
2511 /* Use the subnet mask from the subnet declaration if no other
2512 mask has been provided. */
2513 i = DHO_SUBNET_MASK;
2514 if (!lookup_option (&dhcp_universe, state -> options, i)) {
2515 oc = (struct option_cache *)0;
2516 if (option_cache_allocate (&oc, MDL)) {
2517 if (make_const_data (&oc -> expression,
2518 lease -> subnet -> netmask.iabuf,
2519 lease -> subnet -> netmask.len,
2520 0, 0, MDL)) {
2521 oc -> option = dhcp_universe.options [i];
2522 save_option (&dhcp_universe,
2523 state -> options, oc);
2525 option_cache_dereference (&oc, MDL);
2529 /* Use the hostname from the host declaration if there is one
2530 and no hostname has otherwise been provided, and if the
2531 use-host-decl-name flag is set. */
2532 i = DHO_HOST_NAME;
2533 j = SV_USE_HOST_DECL_NAMES;
2534 if (!lookup_option (&dhcp_universe, state -> options, i) &&
2535 lease -> host && lease -> host -> name &&
2536 (evaluate_boolean_option_cache
2537 (&ignorep, packet, lease, (struct client_state *)0,
2538 packet -> options, state -> options, &lease -> scope,
2539 lookup_option (&server_universe, state -> options, j), MDL))) {
2540 oc = (struct option_cache *)0;
2541 if (option_cache_allocate (&oc, MDL)) {
2542 if (make_const_data (&oc -> expression,
2543 ((unsigned char *)
2544 lease -> host -> name),
2545 strlen (lease -> host -> name),
2546 1, 0, MDL)) {
2547 oc -> option = dhcp_universe.options [i];
2548 save_option (&dhcp_universe,
2549 state -> options, oc);
2551 option_cache_dereference (&oc, MDL);
2555 /* If we don't have a hostname yet, and we've been asked to do
2556 a reverse lookup to find the hostname, do it. */
2557 j = SV_GET_LEASE_HOSTNAMES;
2558 if (!lookup_option (&server_universe, state -> options, i) &&
2559 (evaluate_boolean_option_cache
2560 (&ignorep, packet, lease, (struct client_state *)0,
2561 packet -> options, state -> options, &lease -> scope,
2562 lookup_option (&server_universe, state -> options, j), MDL))) {
2563 struct in_addr ia;
2564 struct hostent *h;
2566 memcpy (&ia, lease -> ip_addr.iabuf, 4);
2568 h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
2569 if (!h)
2570 log_error ("No hostname for %s", inet_ntoa (ia));
2571 else {
2572 oc = (struct option_cache *)0;
2573 if (option_cache_allocate (&oc, MDL)) {
2574 if (make_const_data (&oc -> expression,
2575 ((unsigned char *)
2576 h -> h_name),
2577 strlen (h -> h_name) + 1,
2578 1, 1, MDL)) {
2579 oc -> option =
2580 dhcp_universe.options [i];
2581 save_option (&dhcp_universe,
2582 state -> options, oc);
2584 option_cache_dereference (&oc, MDL);
2589 /* If so directed, use the leased IP address as the router address.
2590 This supposedly makes Win95 machines ARP for all IP addresses,
2591 so if the local router does proxy arp, you win. */
2593 if (evaluate_boolean_option_cache
2594 (&ignorep, packet, lease, (struct client_state *)0,
2595 packet -> options, state -> options, &lease -> scope,
2596 lookup_option (&server_universe, state -> options,
2597 SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
2598 i = DHO_ROUTERS;
2599 oc = lookup_option (&dhcp_universe, state -> options, i);
2600 if (!oc) {
2601 oc = (struct option_cache *)0;
2602 if (option_cache_allocate (&oc, MDL)) {
2603 if (make_const_data (&oc -> expression,
2604 lease -> ip_addr.iabuf,
2605 lease -> ip_addr.len,
2606 0, 0, MDL)) {
2607 oc -> option =
2608 dhcp_universe.options [i];
2609 save_option (&dhcp_universe,
2610 state -> options, oc);
2612 option_cache_dereference (&oc, MDL);
2617 /* If a site option space has been specified, use that for
2618 site option codes. */
2619 i = SV_SITE_OPTION_SPACE;
2620 if ((oc = lookup_option (&server_universe, state -> options, i)) &&
2621 evaluate_option_cache (&d1, packet, lease,
2622 (struct client_state *)0,
2623 packet -> options, state -> options,
2624 &lease -> scope, oc, MDL)) {
2625 struct universe *u = (struct universe *)0;
2627 if (!universe_hash_lookup (&u, universe_hash,
2628 (const char *)d1.data, d1.len,
2629 MDL)) {
2630 log_error ("unknown option space %s.", d1.data);
2631 return;
2634 state -> options -> site_universe = u -> index;
2635 state -> options -> site_code_min = 128; /* XXX */
2636 data_string_forget (&d1, MDL);
2637 } else {
2638 state -> options -> site_code_min = 0;
2639 state -> options -> site_universe = dhcp_universe.index;
2642 /* If the client has provided a list of options that it wishes
2643 returned, use it to prioritize. If there's a parameter
2644 request list in scope, use that in preference. Otherwise
2645 use the default priority list. */
2647 oc = lookup_option (&dhcp_universe, state -> options,
2648 DHO_DHCP_PARAMETER_REQUEST_LIST);
2650 if (!oc)
2651 oc = lookup_option (&dhcp_universe, packet -> options,
2652 DHO_DHCP_PARAMETER_REQUEST_LIST);
2653 if (oc)
2654 evaluate_option_cache (&state -> parameter_request_list,
2655 packet, lease, (struct client_state *)0,
2656 packet -> options, state -> options,
2657 &lease -> scope, oc, MDL);
2659 #ifdef DEBUG_PACKET
2660 dump_packet (packet);
2661 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
2662 #endif
2664 lease -> state = state;
2666 log_info ("%s", msg);
2668 /* Hang the packet off the lease state. */
2669 packet_reference (&lease -> state -> packet, packet, MDL);
2671 /* If this is a DHCPOFFER, ping the lease address before actually
2672 sending the offer. */
2673 if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
2674 cur_time - lease -> timestamp > 60 &&
2675 (!(oc = lookup_option (&server_universe, state -> options,
2676 SV_PING_CHECKS)) ||
2677 evaluate_boolean_option_cache (&ignorep, packet, lease,
2678 (struct client_state *)0,
2679 packet -> options,
2680 state -> options,
2681 &lease -> scope, oc, MDL))) {
2682 lease -> timestamp = cur_time;
2683 icmp_echorequest (&lease -> ip_addr);
2685 /* Determine wether to use configured or default ping timeout.
2687 if ((oc = lookup_option (&server_universe, state -> options,
2688 SV_PING_TIMEOUT)) &&
2689 evaluate_option_cache (&d1, packet, lease, NULL,
2690 packet -> options,
2691 state -> options,
2692 &lease -> scope, oc, MDL)) {
2693 if (d1.len == sizeof (u_int32_t))
2694 ping_timeout = getULong (d1.data);
2695 else
2696 ping_timeout = DEFAULT_PING_TIMEOUT;
2698 data_string_forget (&d1, MDL);
2699 } else
2700 ping_timeout = DEFAULT_PING_TIMEOUT;
2702 #ifdef DEBUG
2703 log_debug ("Ping timeout: %ld", (long)ping_timeout);
2704 #endif
2706 add_timeout (cur_time + ping_timeout, lease_ping_timeout, lease,
2707 (tvref_t)lease_reference,
2708 (tvunref_t)lease_dereference);
2709 ++outstanding_pings;
2710 } else {
2711 lease -> timestamp = cur_time;
2712 dhcp_reply (lease);
2716 void dhcp_reply (lease)
2717 struct lease *lease;
2719 int bufs = 0;
2720 unsigned packet_length;
2721 struct dhcp_packet raw;
2722 struct sockaddr_in to;
2723 struct in_addr from;
2724 struct hardware hto;
2725 int result;
2726 int i;
2727 struct lease_state *state = lease -> state;
2728 int nulltp, bootpp, unicastp = 1;
2729 struct option_tag *ot, *not;
2730 struct data_string d1;
2731 struct option_cache *oc;
2732 const char *s;
2734 if (!state)
2735 log_fatal ("dhcp_reply was supplied lease with no state!");
2737 /* Compose a response for the client... */
2738 memset (&raw, 0, sizeof raw);
2739 memset (&d1, 0, sizeof d1);
2741 /* Copy in the filename if given; otherwise, flag the filename
2742 buffer as available for options. */
2743 if (state -> filename.len && state -> filename.data) {
2744 memcpy (raw.file,
2745 state -> filename.data,
2746 state -> filename.len > sizeof raw.file
2747 ? sizeof raw.file : state -> filename.len);
2748 if (sizeof raw.file > state -> filename.len)
2749 memset (&raw.file [state -> filename.len], 0,
2750 (sizeof raw.file) - state -> filename.len);
2751 } else
2752 bufs |= 1;
2754 /* Copy in the server name if given; otherwise, flag the
2755 server_name buffer as available for options. */
2756 if (state -> server_name.len && state -> server_name.data) {
2757 memcpy (raw.sname,
2758 state -> server_name.data,
2759 state -> server_name.len > sizeof raw.sname
2760 ? sizeof raw.sname : state -> server_name.len);
2761 if (sizeof raw.sname > state -> server_name.len)
2762 memset (&raw.sname [state -> server_name.len], 0,
2763 (sizeof raw.sname) - state -> server_name.len);
2764 } else
2765 bufs |= 2; /* XXX */
2767 memcpy (raw.chaddr,
2768 &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
2769 raw.hlen = lease -> hardware_addr.hlen - 1;
2770 raw.htype = lease -> hardware_addr.hbuf [0];
2772 /* See if this is a Microsoft client that NUL-terminates its
2773 strings and expects us to do likewise... */
2774 if (lease -> flags & MS_NULL_TERMINATION)
2775 nulltp = 1;
2776 else
2777 nulltp = 0;
2779 /* See if this is a bootp client... */
2780 if (state -> offer)
2781 bootpp = 0;
2782 else
2783 bootpp = 1;
2785 /* Insert such options as will fit into the buffer. */
2786 packet_length = cons_options (state -> packet, &raw, lease,
2787 (struct client_state *)0,
2788 state -> max_message_size,
2789 state -> packet -> options,
2790 state -> options, &global_scope,
2791 bufs, nulltp, bootpp,
2792 &state -> parameter_request_list,
2793 (char *)0);
2795 memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
2796 memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
2797 raw.siaddr = state -> siaddr;
2798 raw.giaddr = state -> giaddr;
2800 raw.xid = state -> xid;
2801 raw.secs = state -> secs;
2802 raw.flags = state -> bootp_flags;
2803 raw.hops = state -> hops;
2804 raw.op = BOOTREPLY;
2806 if (lease -> client_hostname) {
2807 if ((strlen (lease -> client_hostname) <= 64) &&
2808 db_printable (lease -> client_hostname))
2809 s = lease -> client_hostname;
2810 else
2811 s = "Hostname Unsuitable for Printing";
2812 } else
2813 s = (char *)0;
2815 /* Say what we're doing... */
2816 log_info ("%s on %s to %s %s%s%svia %s",
2817 (state -> offer
2818 ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
2819 : "BOOTREPLY"),
2820 piaddr (lease -> ip_addr),
2821 (lease -> hardware_addr.hlen
2822 ? print_hw_addr (lease -> hardware_addr.hbuf [0],
2823 lease -> hardware_addr.hlen - 1,
2824 &lease -> hardware_addr.hbuf [1])
2825 : print_hex_1 (lease -> uid_len, lease -> uid,
2826 lease -> uid_len)),
2827 s ? "(" : "", s ? s : "", s ? ") " : "",
2828 (state -> giaddr.s_addr
2829 ? inet_ntoa (state -> giaddr)
2830 : state -> ip -> name));
2832 /* Set up the hardware address... */
2833 hto.hlen = lease -> hardware_addr.hlen;
2834 memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
2836 to.sin_family = AF_INET;
2837 #ifdef HAVE_SA_LEN
2838 to.sin_len = sizeof to;
2839 #endif
2840 memset (to.sin_zero, 0, sizeof to.sin_zero);
2842 #ifdef DEBUG_PACKET
2843 dump_raw ((unsigned char *)&raw, packet_length);
2844 #endif
2846 /* Make sure outgoing packets are at least as big
2847 as a BOOTP packet. */
2848 if (packet_length < BOOTP_MIN_LEN)
2849 packet_length = BOOTP_MIN_LEN;
2851 /* If this was gatewayed, send it back to the gateway... */
2852 if (raw.giaddr.s_addr) {
2853 to.sin_addr = raw.giaddr;
2854 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
2855 to.sin_port = local_port;
2856 else
2857 to.sin_port = remote_port; /* For debugging. */
2859 if (fallback_interface) {
2860 result = send_packet (fallback_interface,
2861 (struct packet *)0,
2862 &raw, packet_length,
2863 raw.siaddr, &to,
2864 (struct hardware *)0);
2866 free_lease_state (state, MDL);
2867 lease -> state = (struct lease_state *)0;
2868 return;
2871 /* If the client is RENEWING, unicast to the client using the
2872 regular IP stack. Some clients, particularly those that
2873 follow RFC1541, are buggy, and send both ciaddr and server
2874 identifier. We deal with this situation by assuming that
2875 if we got both dhcp-server-identifier and ciaddr, and
2876 giaddr was not set, then the client is on the local
2877 network, and we can therefore unicast or broadcast to it
2878 successfully. A client in REQUESTING state on another
2879 network that's making this mistake will have set giaddr,
2880 and will therefore get a relayed response from the above
2881 code. */
2882 } else if (raw.ciaddr.s_addr &&
2883 !((state -> got_server_identifier ||
2884 (raw.flags & htons (BOOTP_BROADCAST))) &&
2885 /* XXX This won't work if giaddr isn't zero, but it is: */
2886 (state -> shared_network ==
2887 lease -> subnet -> shared_network)) &&
2888 state -> offer == DHCPACK) {
2889 to.sin_addr = raw.ciaddr;
2890 to.sin_port = remote_port;
2892 if (fallback_interface) {
2893 result = send_packet (fallback_interface,
2894 (struct packet *)0,
2895 &raw, packet_length,
2896 raw.siaddr, &to,
2897 (struct hardware *)0);
2898 free_lease_state (state, MDL);
2899 lease -> state = (struct lease_state *)0;
2900 return;
2903 /* If it comes from a client that already knows its address
2904 and is not requesting a broadcast response, and we can
2905 unicast to a client without using the ARP protocol, sent it
2906 directly to that client. */
2907 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
2908 can_unicast_without_arp (state -> ip)) {
2909 to.sin_addr = raw.yiaddr;
2910 to.sin_port = remote_port;
2912 /* Otherwise, broadcast it on the local network. */
2913 } else {
2914 to.sin_addr = limited_broadcast;
2915 to.sin_port = remote_port;
2916 if (!(lease -> flags & UNICAST_BROADCAST_HACK))
2917 unicastp = 0;
2920 memcpy (&from, state -> from.iabuf, sizeof from);
2922 result = send_packet (state -> ip,
2923 (struct packet *)0, &raw, packet_length,
2924 from, &to,
2925 unicastp ? &hto : (struct hardware *)0);
2927 /* Free all of the entries in the option_state structure
2928 now that we're done with them. */
2930 free_lease_state (state, MDL);
2931 lease -> state = (struct lease_state *)0;
2934 int find_lease (struct lease **lp,
2935 struct packet *packet, struct shared_network *share, int *ours,
2936 int *allocatedp, struct lease *ip_lease_in,
2937 const char *file, int line)
2939 struct lease *uid_lease = (struct lease *)0;
2940 struct lease *ip_lease = (struct lease *)0;
2941 struct lease *hw_lease = (struct lease *)0;
2942 struct lease *lease = (struct lease *)0;
2943 struct iaddr cip;
2944 struct host_decl *hp = (struct host_decl *)0;
2945 struct host_decl *host = (struct host_decl *)0;
2946 struct lease *fixed_lease = (struct lease *)0;
2947 struct lease *next = (struct lease *)0;
2948 struct option_cache *oc;
2949 struct data_string d1;
2950 int have_client_identifier = 0;
2951 struct data_string client_identifier;
2952 int status;
2953 struct hardware h;
2955 if (packet -> raw -> ciaddr.s_addr) {
2956 cip.len = 4;
2957 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
2958 } else {
2959 /* Look up the requested address. */
2960 oc = lookup_option (&dhcp_universe, packet -> options,
2961 DHO_DHCP_REQUESTED_ADDRESS);
2962 memset (&d1, 0, sizeof d1);
2963 if (oc &&
2964 evaluate_option_cache (&d1, packet, (struct lease *)0,
2965 (struct client_state *)0,
2966 packet -> options,
2967 (struct option_state *)0,
2968 &global_scope, oc, MDL)) {
2969 packet -> got_requested_address = 1;
2970 cip.len = 4;
2971 memcpy (cip.iabuf, d1.data, cip.len);
2972 data_string_forget (&d1, MDL);
2973 } else
2974 cip.len = 0;
2977 /* Try to find a host or lease that's been assigned to the
2978 specified unique client identifier. */
2979 oc = lookup_option (&dhcp_universe, packet -> options,
2980 DHO_DHCP_CLIENT_IDENTIFIER);
2981 memset (&client_identifier, 0, sizeof client_identifier);
2982 if (oc &&
2983 evaluate_option_cache (&client_identifier,
2984 packet, (struct lease *)0,
2985 (struct client_state *)0,
2986 packet -> options, (struct option_state *)0,
2987 &global_scope, oc, MDL)) {
2988 /* Remember this for later. */
2989 have_client_identifier = 1;
2991 /* First, try to find a fixed host entry for the specified
2992 client identifier... */
2993 if (find_hosts_by_uid (&hp, client_identifier.data,
2994 client_identifier.len, MDL)) {
2995 /* Remember if we know of this client. */
2996 packet -> known = 1;
2997 mockup_lease (&fixed_lease, packet, share, hp);
3000 #if defined (DEBUG_FIND_LEASE)
3001 if (fixed_lease) {
3002 log_info ("Found host for client identifier: %s.",
3003 piaddr (fixed_lease -> ip_addr));
3005 #endif
3006 if (hp) {
3007 if (!fixed_lease) /* Save the host if we found one. */
3008 host_reference (&host, hp, MDL);
3009 host_dereference (&hp, MDL);
3012 find_lease_by_uid (&uid_lease, client_identifier.data,
3013 client_identifier.len, MDL);
3016 /* If we didn't find a fixed lease using the uid, try doing
3017 it with the hardware address... */
3018 if (!fixed_lease && !host) {
3019 if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
3020 packet -> raw -> chaddr,
3021 packet -> raw -> hlen, MDL)) {
3022 /* Remember if we know of this client. */
3023 packet -> known = 1;
3024 if (host)
3025 host_dereference (&host, MDL);
3026 host_reference (&host, hp, MDL);
3027 host_dereference (&hp, MDL);
3028 mockup_lease (&fixed_lease, packet, share, host);
3029 #if defined (DEBUG_FIND_LEASE)
3030 if (fixed_lease) {
3031 log_info ("Found host for link address: %s.",
3032 piaddr (fixed_lease -> ip_addr));
3034 #endif
3038 /* If fixed_lease is present but does not match the requested
3039 IP address, and this is a DHCPREQUEST, then we can't return
3040 any other lease, so we might as well return now. */
3041 if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
3042 (fixed_lease -> ip_addr.len != cip.len ||
3043 memcmp (fixed_lease -> ip_addr.iabuf,
3044 cip.iabuf, cip.len))) {
3045 if (ours)
3046 *ours = 1;
3047 strcpy (dhcp_message, "requested address is incorrect");
3048 #if defined (DEBUG_FIND_LEASE)
3049 log_info ("Client's fixed-address %s doesn't match %s%s",
3050 piaddr (fixed_lease -> ip_addr), "request ",
3051 print_dotted_quads (cip.len, cip.iabuf));
3052 #endif
3053 goto out;
3056 /* If we found leases matching the client identifier, loop through
3057 the n_uid pointer looking for one that's actually valid. We
3058 can't do this until we get here because we depend on
3059 packet -> known, which may be set by either the uid host
3060 lookup or the haddr host lookup. */
3061 while (uid_lease) {
3062 #if defined (DEBUG_FIND_LEASE)
3063 log_info ("trying next lease matching client id: %s",
3064 piaddr (uid_lease -> ip_addr));
3065 #endif
3067 #if defined (FAILOVER_PROTOCOL)
3068 /* When failover is active, it's possible that there could
3069 be two "free" leases for the same uid, but only one of
3070 them that's available for this failover peer to allocate. */
3071 if (uid_lease -> binding_state != FTS_ACTIVE &&
3072 !lease_mine_to_reallocate (uid_lease)) {
3073 #if defined (DEBUG_FIND_LEASE)
3074 log_info ("not mine to allocate: %s",
3075 piaddr (uid_lease -> ip_addr));
3076 #endif
3077 goto n_uid;
3079 #endif
3081 if (uid_lease -> subnet -> shared_network != share) {
3082 #if defined (DEBUG_FIND_LEASE)
3083 log_info ("wrong network segment: %s",
3084 piaddr (uid_lease -> ip_addr));
3085 #endif
3086 goto n_uid;
3089 if ((uid_lease -> pool -> prohibit_list &&
3090 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
3091 (uid_lease -> pool -> permit_list &&
3092 !permitted (packet, uid_lease -> pool -> permit_list))) {
3093 #if defined (DEBUG_FIND_LEASE)
3094 log_info ("not permitted: %s",
3095 piaddr (uid_lease -> ip_addr));
3096 #endif
3097 n_uid:
3098 if (uid_lease -> n_uid)
3099 lease_reference (&next,
3100 uid_lease -> n_uid, MDL);
3101 if (!packet -> raw -> ciaddr.s_addr)
3102 release_lease (uid_lease, packet);
3103 lease_dereference (&uid_lease, MDL);
3104 if (next) {
3105 lease_reference (&uid_lease, next, MDL);
3106 lease_dereference (&next, MDL);
3108 continue;
3110 break;
3112 #if defined (DEBUG_FIND_LEASE)
3113 if (uid_lease)
3114 log_info ("Found lease for client id: %s.",
3115 piaddr (uid_lease -> ip_addr));
3116 #endif
3118 /* Find a lease whose hardware address matches, whose client
3119 identifier matches, that's permitted, and that's on the
3120 correct subnet. */
3121 h.hlen = packet -> raw -> hlen + 1;
3122 h.hbuf [0] = packet -> raw -> htype;
3123 memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
3124 find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
3125 while (hw_lease) {
3126 #if defined (DEBUG_FIND_LEASE)
3127 log_info ("trying next lease matching hw addr: %s",
3128 piaddr (hw_lease -> ip_addr));
3129 #endif
3130 #if defined (FAILOVER_PROTOCOL)
3131 /* When failover is active, it's possible that there could
3132 be two "free" leases for the same uid, but only one of
3133 them that's available for this failover peer to allocate. */
3134 if (hw_lease -> binding_state != FTS_ACTIVE &&
3135 !lease_mine_to_reallocate (hw_lease)) {
3136 #if defined (DEBUG_FIND_LEASE)
3137 log_info ("not mine to allocate: %s",
3138 piaddr (hw_lease -> ip_addr));
3139 #endif
3140 goto n_hw;
3142 #endif
3144 if (hw_lease -> binding_state != FTS_FREE &&
3145 hw_lease -> binding_state != FTS_BACKUP &&
3146 hw_lease -> uid &&
3147 (!have_client_identifier ||
3148 hw_lease -> uid_len != client_identifier.len ||
3149 memcmp (hw_lease -> uid, client_identifier.data,
3150 hw_lease -> uid_len))) {
3151 #if defined (DEBUG_FIND_LEASE)
3152 log_info ("wrong client identifier: %s",
3153 piaddr (hw_lease -> ip_addr));
3154 #endif
3155 goto n_hw;
3156 continue;
3158 if (hw_lease -> subnet -> shared_network != share) {
3159 #if defined (DEBUG_FIND_LEASE)
3160 log_info ("wrong network segment: %s",
3161 piaddr (hw_lease -> ip_addr));
3162 #endif
3163 goto n_hw;
3164 continue;
3166 if ((hw_lease -> pool -> prohibit_list &&
3167 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
3168 (hw_lease -> pool -> permit_list &&
3169 !permitted (packet, hw_lease -> pool -> permit_list))) {
3170 #if defined (DEBUG_FIND_LEASE)
3171 log_info ("not permitted: %s",
3172 piaddr (hw_lease -> ip_addr));
3173 #endif
3174 if (!packet -> raw -> ciaddr.s_addr)
3175 release_lease (hw_lease, packet);
3176 n_hw:
3177 if (hw_lease -> n_hw)
3178 lease_reference (&next, hw_lease -> n_hw, MDL);
3179 lease_dereference (&hw_lease, MDL);
3180 if (next) {
3181 lease_reference (&hw_lease, next, MDL);
3182 lease_dereference (&next, MDL);
3184 continue;
3186 break;
3188 #if defined (DEBUG_FIND_LEASE)
3189 if (hw_lease)
3190 log_info ("Found lease for hardware address: %s.",
3191 piaddr (hw_lease -> ip_addr));
3192 #endif
3194 /* Try to find a lease that's been allocated to the client's
3195 IP address. */
3196 if (ip_lease_in)
3197 lease_reference (&ip_lease, ip_lease_in, MDL);
3198 else if (cip.len)
3199 find_lease_by_ip_addr (&ip_lease, cip, MDL);
3201 #if defined (DEBUG_FIND_LEASE)
3202 if (ip_lease)
3203 log_info ("Found lease for requested address: %s.",
3204 piaddr (ip_lease -> ip_addr));
3205 #endif
3207 /* If ip_lease is valid at this point, set ours to one, so that
3208 even if we choose a different lease, we know that the address
3209 the client was requesting was ours, and thus we can NAK it. */
3210 if (ip_lease && ours)
3211 *ours = 1;
3213 /* If the requested IP address isn't on the network the packet
3214 came from, don't use it. Allow abandoned leases to be matched
3215 here - if the client is requesting it, there's a decent chance
3216 that it's because the lease database got trashed and a client
3217 that thought it had this lease answered an ARP or PING, causing the
3218 lease to be abandoned. If so, this request probably came from
3219 that client. */
3220 if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
3221 if (ours)
3222 *ours = 1;
3223 #if defined (DEBUG_FIND_LEASE)
3224 log_info ("...but it was on the wrong shared network.");
3225 #endif
3226 strcpy (dhcp_message, "requested address on bad subnet");
3227 lease_dereference (&ip_lease, MDL);
3230 /* Toss ip_lease if it hasn't yet expired and doesn't belong to the
3231 client. */
3232 if (ip_lease &&
3233 (ip_lease -> uid ?
3234 (!have_client_identifier ||
3235 ip_lease -> uid_len != client_identifier.len ||
3236 memcmp (ip_lease -> uid, client_identifier.data,
3237 ip_lease -> uid_len)) :
3238 (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
3239 ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
3240 memcmp (&ip_lease -> hardware_addr.hbuf [1],
3241 packet -> raw -> chaddr,
3242 (unsigned)(ip_lease -> hardware_addr.hlen - 1))))) {
3243 /* If we're not doing failover, the only state in which
3244 we can allocate this lease to the client is FTS_FREE.
3245 If we are doing failover, things are more complicated.
3246 If the lease is free or backup, we let the caller decide
3247 whether or not to give it out. */
3248 if (ip_lease -> binding_state != FTS_FREE &&
3249 ip_lease -> binding_state != FTS_BACKUP) {
3250 #if defined (DEBUG_FIND_LEASE)
3251 log_info ("rejecting lease for requested address.");
3252 #endif
3253 /* If we're rejecting it because the peer has
3254 it, don't set "ours", because we shouldn't NAK. */
3255 if (ours && ip_lease -> binding_state != FTS_ACTIVE)
3256 *ours = 0;
3257 lease_dereference (&ip_lease, MDL);
3258 } else
3259 if (allocatedp)
3260 *allocatedp = 1;
3263 /* If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
3264 is not active, and is not ours to reallocate, forget about it. */
3265 if (ip_lease && (uid_lease || hw_lease) &&
3266 ip_lease -> binding_state != FTS_ACTIVE &&
3267 !lease_mine_to_reallocate (ip_lease) &&
3268 packet -> packet_type == DHCPDISCOVER) {
3269 #if defined (DEBUG_FIND_LEASE)
3270 log_info ("ip lease not ours to offer.");
3271 #endif
3272 lease_dereference (&ip_lease, MDL);
3275 /* If for some reason the client has more than one lease
3276 on the subnet that matches its uid, pick the one that
3277 it asked for and (if we can) free the other. */
3278 if (ip_lease &&
3279 ip_lease -> binding_state == FTS_ACTIVE &&
3280 ip_lease -> uid && ip_lease != uid_lease) {
3281 if (have_client_identifier &&
3282 (ip_lease -> uid_len == client_identifier.len) &&
3283 !memcmp (client_identifier.data,
3284 ip_lease -> uid, ip_lease -> uid_len)) {
3285 if (uid_lease) {
3286 if (uid_lease -> binding_state == FTS_ACTIVE) {
3287 log_error ("client %s has duplicate%s on %s",
3288 (print_hw_addr
3289 (packet -> raw -> htype,
3290 packet -> raw -> hlen,
3291 packet -> raw -> chaddr)),
3292 " leases",
3293 (ip_lease -> subnet ->
3294 shared_network -> name));
3296 /* If the client is REQUESTing the lease,
3297 it shouldn't still be using the old
3298 one, so we can free it for allocation. */
3299 if (uid_lease &&
3300 uid_lease -> binding_state == FTS_ACTIVE &&
3301 !packet -> raw -> ciaddr.s_addr &&
3302 (share ==
3303 uid_lease -> subnet -> shared_network) &&
3304 packet -> packet_type == DHCPREQUEST)
3305 dissociate_lease (uid_lease);
3307 lease_dereference (&uid_lease, MDL);
3308 lease_reference (&uid_lease, ip_lease, MDL);
3312 /* If we get to here and fixed_lease is not null, that means
3313 that there are both a dynamic lease and a fixed-address
3314 declaration for the same IP address. */
3315 if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
3316 lease_dereference (&fixed_lease, MDL);
3317 db_conflict:
3318 log_error ("Dynamic and static leases present for %s.",
3319 piaddr (cip));
3320 log_error ("Remove host declaration %s or remove %s",
3321 (fixed_lease && fixed_lease -> host
3322 ? (fixed_lease -> host -> name
3323 ? fixed_lease -> host -> name
3324 : piaddr (cip))
3325 : piaddr (cip)),
3326 piaddr (cip));
3327 log_error ("from the dynamic address pool for %s",
3328 ip_lease -> subnet -> shared_network -> name
3330 if (fixed_lease)
3331 lease_dereference (&ip_lease, MDL);
3332 strcpy (dhcp_message,
3333 "database conflict - call for help!");
3336 if (ip_lease && ip_lease != uid_lease) {
3337 #if defined (DEBUG_FIND_LEASE)
3338 log_info ("requested address not available.");
3339 #endif
3340 lease_dereference (&ip_lease, MDL);
3344 /* If we get to here with both fixed_lease and ip_lease not
3345 null, then we have a configuration file bug. */
3346 if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
3347 goto db_conflict;
3349 /* Toss extra pointers to the same lease... */
3350 if (hw_lease && hw_lease == uid_lease) {
3351 #if defined (DEBUG_FIND_LEASE)
3352 log_info ("hardware lease and uid lease are identical.");
3353 #endif
3354 lease_dereference (&hw_lease, MDL);
3356 if (ip_lease && ip_lease == hw_lease) {
3357 lease_dereference (&hw_lease, MDL);
3358 #if defined (DEBUG_FIND_LEASE)
3359 log_info ("hardware lease and ip lease are identical.");
3360 #endif
3362 if (ip_lease && ip_lease == uid_lease) {
3363 lease_dereference (&uid_lease, MDL);
3364 #if defined (DEBUG_FIND_LEASE)
3365 log_info ("uid lease and ip lease are identical.");
3366 #endif
3369 /* Make sure the client is permitted to use the requested lease. */
3370 if (ip_lease &&
3371 ((ip_lease -> pool -> prohibit_list &&
3372 permitted (packet, ip_lease -> pool -> prohibit_list)) ||
3373 (ip_lease -> pool -> permit_list &&
3374 !permitted (packet, ip_lease -> pool -> permit_list)))) {
3375 if (!packet -> raw -> ciaddr.s_addr)
3376 release_lease (ip_lease, packet);
3377 lease_dereference (&ip_lease, MDL);
3380 if (uid_lease &&
3381 ((uid_lease -> pool -> prohibit_list &&
3382 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
3383 (uid_lease -> pool -> permit_list &&
3384 !permitted (packet, uid_lease -> pool -> permit_list)))) {
3385 if (!packet -> raw -> ciaddr.s_addr)
3386 release_lease (uid_lease, packet);
3387 lease_dereference (&uid_lease, MDL);
3390 if (hw_lease &&
3391 ((hw_lease -> pool -> prohibit_list &&
3392 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
3393 (hw_lease -> pool -> permit_list &&
3394 !permitted (packet, hw_lease -> pool -> permit_list)))) {
3395 if (!packet -> raw -> ciaddr.s_addr)
3396 release_lease (hw_lease, packet);
3397 lease_dereference (&hw_lease, MDL);
3400 /* If we've already eliminated the lease, it wasn't there to
3401 begin with. If we have come up with a matching lease,
3402 set the message to bad network in case we have to throw it out. */
3403 if (!ip_lease) {
3404 strcpy (dhcp_message, "requested address not available");
3407 /* If this is a DHCPREQUEST, make sure the lease we're going to return
3408 matches the requested IP address. If it doesn't, don't return a
3409 lease at all. */
3410 if (packet -> packet_type == DHCPREQUEST &&
3411 !ip_lease && !fixed_lease) {
3412 #if defined (DEBUG_FIND_LEASE)
3413 log_info ("no applicable lease found for DHCPREQUEST.");
3414 #endif
3415 goto out;
3418 /* At this point, if fixed_lease is nonzero, we can assign it to
3419 this client. */
3420 if (fixed_lease) {
3421 lease_reference (&lease, fixed_lease, MDL);
3422 lease_dereference (&fixed_lease, MDL);
3423 #if defined (DEBUG_FIND_LEASE)
3424 log_info ("choosing fixed address.");
3425 #endif
3428 /* If we got a lease that matched the ip address and don't have
3429 a better offer, use that; otherwise, release it. */
3430 if (ip_lease) {
3431 if (lease) {
3432 if (!packet -> raw -> ciaddr.s_addr)
3433 release_lease (ip_lease, packet);
3434 #if defined (DEBUG_FIND_LEASE)
3435 log_info ("not choosing requested address (!).");
3436 #endif
3437 } else {
3438 #if defined (DEBUG_FIND_LEASE)
3439 log_info ("choosing lease on requested address.");
3440 #endif
3441 lease_reference (&lease, ip_lease, MDL);
3442 if (lease -> host)
3443 host_dereference (&lease -> host, MDL);
3445 lease_dereference (&ip_lease, MDL);
3448 /* If we got a lease that matched the client identifier, we may want
3449 to use it, but if we already have a lease we like, we must free
3450 the lease that matched the client identifier. */
3451 if (uid_lease) {
3452 if (lease) {
3453 if (!packet -> raw -> ciaddr.s_addr &&
3454 packet -> packet_type == DHCPREQUEST &&
3455 uid_lease -> binding_state == FTS_ACTIVE)
3456 dissociate_lease (uid_lease);
3457 #if defined (DEBUG_FIND_LEASE)
3458 log_info ("not choosing uid lease.");
3459 #endif
3460 } else {
3461 lease_reference (&lease, uid_lease, MDL);
3462 if (lease -> host)
3463 host_dereference (&lease -> host, MDL);
3464 #if defined (DEBUG_FIND_LEASE)
3465 log_info ("choosing uid lease.");
3466 #endif
3468 lease_dereference (&uid_lease, MDL);
3471 /* The lease that matched the hardware address is treated likewise. */
3472 if (hw_lease) {
3473 if (lease) {
3474 #if defined (DEBUG_FIND_LEASE)
3475 log_info ("not choosing hardware lease.");
3476 #endif
3477 } else {
3478 /* We're a little lax here - if the client didn't
3479 send a client identifier and it's a bootp client,
3480 but the lease has a client identifier, we still
3481 let the client have a lease. */
3482 if (!hw_lease -> uid_len ||
3483 (have_client_identifier
3484 ? (hw_lease -> uid_len ==
3485 client_identifier.len &&
3486 !memcmp (hw_lease -> uid,
3487 client_identifier.data,
3488 client_identifier.len))
3489 : packet -> packet_type == 0)) {
3490 lease_reference (&lease, hw_lease, MDL);
3491 if (lease -> host)
3492 host_dereference (&lease -> host, MDL);
3493 #if defined (DEBUG_FIND_LEASE)
3494 log_info ("choosing hardware lease.");
3495 #endif
3496 } else {
3497 #if defined (DEBUG_FIND_LEASE)
3498 log_info ("not choosing hardware lease: %s.",
3499 "uid mismatch");
3500 #endif
3503 lease_dereference (&hw_lease, MDL);
3506 /* If we found a host_decl but no matching address, try to
3507 find a host_decl that has no address, and if there is one,
3508 hang it off the lease so that we can use the supplied
3509 options. */
3510 if (lease && host && !lease -> host) {
3511 struct host_decl *p = (struct host_decl *)0;
3512 struct host_decl *n = (struct host_decl *)0;
3513 host_reference (&p, host, MDL);
3514 while (p) {
3515 if (!p -> fixed_addr) {
3516 host_reference (&lease -> host, p, MDL);
3517 host_dereference (&p, MDL);
3518 break;
3520 if (p -> n_ipaddr)
3521 host_reference (&n, p -> n_ipaddr, MDL);
3522 host_dereference (&p, MDL);
3523 if (n) {
3524 host_reference (&p, n, MDL);
3525 host_dereference (&n, MDL);
3530 /* If we find an abandoned lease, but it's the one the client
3531 requested, we assume that previous bugginess on the part
3532 of the client, or a server database loss, caused the lease to
3533 be abandoned, so we reclaim it and let the client have it. */
3534 if (lease &&
3535 (lease -> binding_state == FTS_ABANDONED) &&
3536 lease == ip_lease &&
3537 packet -> packet_type == DHCPREQUEST) {
3538 log_error ("Reclaiming REQUESTed abandoned IP address %s.",
3539 piaddr (lease -> ip_addr));
3540 } else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
3541 /* Otherwise, if it's not the one the client requested, we do not
3542 return it - instead, we claim it's ours, causing a DHCPNAK to be
3543 sent if this lookup is for a DHCPREQUEST, and force the client
3544 to go back through the allocation process. */
3545 if (ours)
3546 *ours = 1;
3547 lease_dereference (&lease, MDL);
3550 if (lease && allocatedp && lease -> ends <= cur_time)
3551 *allocatedp = 1;
3553 out:
3554 if (have_client_identifier)
3555 data_string_forget (&client_identifier, MDL);
3557 if (fixed_lease)
3558 lease_dereference (&fixed_lease, MDL);
3559 if (hw_lease)
3560 lease_dereference (&hw_lease, MDL);
3561 if (uid_lease)
3562 lease_dereference (&uid_lease, MDL);
3563 if (ip_lease)
3564 lease_dereference (&ip_lease, MDL);
3565 if (host)
3566 host_dereference (&host, MDL);
3568 if (lease) {
3569 #if defined (DEBUG_FIND_LEASE)
3570 log_info ("Returning lease: %s.",
3571 piaddr (lease -> ip_addr));
3572 #endif
3573 lease_reference (lp, lease, file, line);
3574 lease_dereference (&lease, MDL);
3575 return 1;
3577 #if defined (DEBUG_FIND_LEASE)
3578 log_info ("Not returning a lease.");
3579 #endif
3580 return 0;
3583 /* Search the provided host_decl structure list for an address that's on
3584 the specified shared network. If one is found, mock up and return a
3585 lease structure for it; otherwise return the null pointer. */
3587 int mockup_lease (struct lease **lp, struct packet *packet,
3588 struct shared_network *share, struct host_decl *hp)
3590 struct lease *lease = (struct lease *)0;
3591 struct host_decl *rhp = (struct host_decl *)0;
3593 if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS)
3594 return 0;
3595 if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) {
3596 lease_dereference (&lease, MDL);
3597 return 0;
3599 if (!find_host_for_network (&lease -> subnet,
3600 &rhp, &lease -> ip_addr, share)) {
3601 lease_dereference (&lease, MDL);
3602 host_dereference (&rhp, MDL);
3603 return 0;
3605 host_reference (&lease -> host, rhp, MDL);
3606 if (rhp -> client_identifier.len > sizeof lease -> uid_buf)
3607 lease -> uid = dmalloc (rhp -> client_identifier.len, MDL);
3608 else
3609 lease -> uid = lease -> uid_buf;
3610 if (!lease -> uid) {
3611 lease_dereference (&lease, MDL);
3612 host_dereference (&rhp, MDL);
3613 return 0;
3615 memcpy (lease -> uid, rhp -> client_identifier.data,
3616 rhp -> client_identifier.len);
3617 lease -> uid_len = rhp -> client_identifier.len;
3618 lease -> hardware_addr = rhp -> interface;
3619 lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
3620 lease -> flags = STATIC_LEASE;
3621 lease -> binding_state = FTS_FREE;
3623 lease_reference (lp, lease, MDL);
3625 lease_dereference (&lease, MDL);
3626 host_dereference (&rhp, MDL);
3627 return 1;
3630 /* Look through all the pools in a list starting with the specified pool
3631 for a free lease. We try to find a virgin lease if we can. If we
3632 don't find a virgin lease, we try to find a non-virgin lease that's
3633 free. If we can't find one of those, we try to reclaim an abandoned
3634 lease. If all of these possibilities fail to pan out, we don't return
3635 a lease at all. */
3637 int allocate_lease (struct lease **lp, struct packet *packet,
3638 struct pool *pool, int *peer_has_leases)
3640 struct lease *lease = (struct lease *)0;
3641 struct lease *candl = (struct lease *)0;
3643 for (; pool ; pool = pool -> next) {
3644 if ((pool -> prohibit_list &&
3645 permitted (packet, pool -> prohibit_list)) ||
3646 (pool -> permit_list &&
3647 !permitted (packet, pool -> permit_list)))
3648 continue;
3650 #if defined (FAILOVER_PROTOCOL)
3651 /* Peer_has_leases just says that we found at least one
3652 free lease. If no free lease is returned, the caller
3653 can deduce that this means the peer is hogging all the
3654 free leases, so we can print a better error message. */
3655 /* XXX Do we need code here to ignore PEER_IS_OWNER and
3656 * XXX just check tstp if we're in, e.g., PARTNER_DOWN?
3657 * XXX Where do we deal with CONFLICT_DETECTED, et al? */
3658 /* XXX This should be handled by the lease binding "state
3659 * XXX machine" - that is, when we get here, if a lease
3660 * XXX could be allocated, it will have the correct
3661 * XXX binding state so that the following code will
3662 * XXX result in its being allocated. */
3663 /* Skip to the most expired lease in the pool that is not
3664 * owned by a failover peer. */
3665 if (pool -> failover_peer) {
3666 if (pool -> failover_peer -> i_am == primary) {
3667 if (pool -> backup)
3668 *peer_has_leases = 1;
3669 candl = pool -> free;
3670 if (!candl)
3671 candl = pool -> abandoned;
3672 } else {
3673 if (pool -> free)
3674 *peer_has_leases = 1;
3675 candl = pool -> backup;
3677 } else
3678 #endif
3680 if (pool -> free)
3681 candl = pool -> free;
3682 else
3683 candl = pool -> abandoned;
3686 if (!candl || (candl -> ends > cur_time))
3687 continue;
3689 if (!lease) {
3690 lease = candl;
3691 continue;
3694 if ((lease -> binding_state == FTS_ABANDONED) &&
3695 ((candl -> binding_state != FTS_ABANDONED) ||
3696 (candl -> ends < lease -> ends))) {
3697 lease = candl;
3698 continue;
3699 } else if (candl -> binding_state == FTS_ABANDONED)
3700 continue;
3702 if ((lease -> uid_len || lease -> hardware_addr.hlen) &&
3703 ((!candl -> uid_len && !candl -> hardware_addr.hlen) ||
3704 (candl -> ends < lease -> ends))) {
3705 lease = candl;
3706 continue;
3707 } else if (candl -> uid_len || candl -> hardware_addr.hlen)
3708 continue;
3710 if (candl -> ends < lease -> ends)
3711 lease = candl;
3714 if (lease) {
3715 if (lease -> binding_state == FTS_ABANDONED)
3716 log_error ("Reclaiming abandoned lease %s.",
3717 piaddr (lease -> ip_addr));
3719 lease_reference (lp, lease, MDL);
3720 return 1;
3723 return 0;
3726 /* Determine whether or not a permit exists on a particular permit list
3727 that matches the specified packet, returning nonzero if so, zero if
3728 not. */
3730 int permitted (packet, permit_list)
3731 struct packet *packet;
3732 struct permit *permit_list;
3734 struct permit *p;
3735 int i;
3737 for (p = permit_list; p; p = p -> next) {
3738 switch (p -> type) {
3739 case permit_unknown_clients:
3740 if (!packet -> known)
3741 return 1;
3742 break;
3744 case permit_known_clients:
3745 if (packet -> known)
3746 return 1;
3747 break;
3749 case permit_authenticated_clients:
3750 if (packet -> authenticated)
3751 return 1;
3752 break;
3754 case permit_unauthenticated_clients:
3755 if (!packet -> authenticated)
3756 return 1;
3757 break;
3759 case permit_all_clients:
3760 return 1;
3762 case permit_dynamic_bootp_clients:
3763 if (!packet -> options_valid ||
3764 !packet -> packet_type)
3765 return 1;
3766 break;
3768 case permit_class:
3769 for (i = 0; i < packet -> class_count; i++) {
3770 if (p -> class == packet -> classes [i])
3771 return 1;
3772 if (packet -> classes [i] &&
3773 packet -> classes [i] -> superclass &&
3774 (packet -> classes [i] -> superclass ==
3775 p -> class))
3776 return 1;
3778 break;
3781 return 0;
3784 int locate_network (packet)
3785 struct packet *packet;
3787 struct iaddr ia;
3788 struct data_string data;
3789 struct subnet *subnet = (struct subnet *)0;
3790 struct option_cache *oc;
3792 /* See if there's a subnet selection option. */
3793 oc = lookup_option (&dhcp_universe, packet -> options,
3794 DHO_SUBNET_SELECTION);
3796 /* If there's no SSO and no giaddr, then use the shared_network
3797 from the interface, if there is one. If not, fail. */
3798 if (!oc && !packet -> raw -> giaddr.s_addr) {
3799 if (packet -> interface -> shared_network) {
3800 shared_network_reference
3801 (&packet -> shared_network,
3802 packet -> interface -> shared_network, MDL);
3803 return 1;
3805 return 0;
3808 /* If there's an SSO, and it's valid, use it to figure out the
3809 subnet. If it's not valid, fail. */
3810 if (oc) {
3811 memset (&data, 0, sizeof data);
3812 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
3813 (struct client_state *)0,
3814 packet -> options,
3815 (struct option_state *)0,
3816 &global_scope, oc, MDL)) {
3817 return 0;
3819 if (data.len != 4) {
3820 return 0;
3822 ia.len = 4;
3823 memcpy (ia.iabuf, data.data, 4);
3824 data_string_forget (&data, MDL);
3825 } else {
3826 ia.len = 4;
3827 memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
3830 /* If we know the subnet on which the IP address lives, use it. */
3831 if (find_subnet (&subnet, ia, MDL)) {
3832 shared_network_reference (&packet -> shared_network,
3833 subnet -> shared_network, MDL);
3834 subnet_dereference (&subnet, MDL);
3835 return 1;
3838 /* Otherwise, fail. */
3839 return 0;