]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/dhcp.c
- Fix all the OMAPI objects in the DHCP server and client that weren't
[thirdparty/dhcp.git] / server / dhcp.c
CommitLineData
d7837182
TL
1/* dhcp.c
2
b88e8e15 3 DHCP Protocol engine. */
d7837182
TL
4
5/*
49733f31
TL
6 * Copyright (c) 1995-2000 Internet Software Consortium.
7 * All rights reserved.
d7837182 8 *
49733f31
TL
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
d7837182 12 *
49733f31
TL
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
d7837182 21 *
49733f31
TL
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
d7837182
TL
42 */
43
44#ifndef lint
45static char copyright[] =
20916cae 46"$Id: dhcp.c,v 1.149 2000/05/16 23:03:42 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
d7837182
TL
47#endif /* not lint */
48
49#include "dhcpd.h"
50
4b7df707
TL
51int outstanding_pings;
52
a7822eac 53static char dhcp_message [256];
b88e8e15 54
d7837182
TL
55void dhcp (packet)
56 struct packet *packet;
57{
5bc2e1f2 58 int ms_nulltp = 0;
c99a6692 59 struct option_cache *oc;
5bc2e1f2 60
d00ecc3c 61 if (!locate_network (packet) && packet -> packet_type != DHCPREQUEST)
3a581108
TL
62 return;
63
b3f15965 64 /* Classify the client. */
5bc2e1f2
TL
65 if ((oc = lookup_option (&dhcp_universe, packet -> options,
66 DHO_HOST_NAME))) {
67 if (!oc -> expression)
68 if (oc -> data.len &&
69 oc -> data.data [oc -> data.len - 1] == 0) {
70 ms_nulltp = 1;
71 oc -> data.len--;
72 }
73 }
74
b3f15965
TL
75 classify_client (packet);
76
ed8bcd8f
TL
77 switch (packet -> packet_type) {
78 case DHCPDISCOVER:
5bc2e1f2 79 dhcpdiscover (packet, ms_nulltp);
ed8bcd8f 80 break;
97ca1699 81
ed8bcd8f 82 case DHCPREQUEST:
5bc2e1f2 83 dhcprequest (packet, ms_nulltp);
ed8bcd8f 84 break;
97ca1699 85
ed8bcd8f 86 case DHCPRELEASE:
5bc2e1f2 87 dhcprelease (packet, ms_nulltp);
ed8bcd8f 88 break;
97ca1699 89
b88e8e15 90 case DHCPDECLINE:
5bc2e1f2 91 dhcpdecline (packet, ms_nulltp);
b88e8e15
TL
92 break;
93
94 case DHCPINFORM:
5bc2e1f2 95 dhcpinform (packet, ms_nulltp);
b88e8e15
TL
96 break;
97
ed8bcd8f
TL
98 default:
99 break;
97ca1699 100 }
ed8bcd8f 101}
97ca1699 102
5bc2e1f2 103void dhcpdiscover (packet, ms_nulltp)
ed8bcd8f 104 struct packet *packet;
5bc2e1f2 105 int ms_nulltp;
ed8bcd8f 106{
20916cae 107 struct lease *lease = (struct lease *)0;
d9eefc5d 108 char msgbuf [1024]; /* XXX */
ffdcd127 109 TIME when;
d9eefc5d 110 char *s;
33225687
TL
111 int allocatedp = 0;
112 int peer_has_leases = 0;
113#if defined (FAILOVER_PROTOCOL)
114 dhcp_failover_state_t *peer;
115#endif
a8b53b42 116
20916cae 117 find_lease (&lease, packet, packet -> shared_network, 0, MDL);
5941275a 118
d9eefc5d
TL
119 if (lease && lease -> client_hostname &&
120 db_printable (lease -> client_hostname))
121 s = lease -> client_hostname;
122 else
123 s = (char *)0;
124
125 /* Say what we're doing... */
126 sprintf (msgbuf, "DHCPDISCOVER from %s %s%s%svia %s",
127 (packet -> raw -> htype
128 ? print_hw_addr (packet -> raw -> htype,
129 packet -> raw -> hlen,
fdd46b53 130 packet -> raw -> chaddr)
d9eefc5d
TL
131 : (lease
132 ? print_hex_1 (lease -> uid_len, lease -> uid,
133 lease -> uid_len)
134 : "<no identifier>")),
135 s ? "(" : "", s ? s : "", s ? ") " : "",
136 packet -> raw -> giaddr.s_addr
137 ? inet_ntoa (packet -> raw -> giaddr)
138 : packet -> interface -> name);
139
33225687
TL
140#if defined (FAILOVER_PROTOCOL)
141 if (lease && lease -> pool &&
142 lease -> pool -> failover_peer) {
143 peer = lease -> pool -> failover_peer;
144 if ((lease -> flags & PEER_IS_OWNER) &&
145 peer -> my_state == normal) {
146 log_info ("%s: letting peer %s respond.",
147 msgbuf, peer -> name);
20916cae 148 goto out;
33225687
TL
149 }
150 }
151#endif
152
15c00bba
TL
153 /* Sourceless packets don't make sense here. */
154 if (!packet -> shared_network) {
8ae2d595 155 log_info ("Packet from unknown subnet: %s",
15c00bba 156 inet_ntoa (packet -> raw -> giaddr));
20916cae 157 goto out;
15c00bba
TL
158 }
159
97ca1699
TL
160 /* If we didn't find a lease, try to allocate one... */
161 if (!lease) {
20916cae
TL
162 if (!allocate_lease (&lease, packet,
163 packet -> shared_network -> pools,
164 &peer_has_leases)) {
33225687
TL
165 if (peer_has_leases)
166 log_info ("%s: peer holds all free leases",
167 msgbuf);
168 else
169 log_info ("%s: network %s: no free leases",
170 msgbuf,
171 packet -> shared_network -> name);
97ca1699
TL
172 return;
173 }
8c8e27c5
TL
174#if defined (FAILOVER_PROTOCOL)
175 if (lease -> pool && lease -> pool -> failover_peer)
176 dhcp_failover_pool_check (lease -> pool);
177#endif
33225687 178 allocatedp = 1;
97ca1699
TL
179 }
180
150cedd0 181#if defined (FAILOVER_PROTOCOL)
150cedd0 182 /* Do load balancing if configured. */
33225687
TL
183 /* If the lease is newly allocated, and we're not the server that
184 the client would normally get with load balancing, and the
185 failover protocol state is normal, let the other server get this.
186 XXX Check protocol spec to make sure that predicating this on
187 XXX allocatedp is okay - I'm doing this so that the client won't
188 XXX be forced to switch servers (and IP addresses) just because
189 XXX of bad luck, when it's possible for it to get the address it
190 XXX is requesting. Not sure this is allowed. */
191 if (allocatedp && lease && lease -> pool &&
192 lease -> pool -> failover_peer) {
193 peer = lease -> pool -> failover_peer;
194 if (peer -> hba && peer -> my_state == normal) {
195 if (!load_balance_mine (packet, peer)) {
196 log_debug ("%s: load balance to peer %s",
197 msgbuf, peer -> name);
20916cae 198 goto out;
33225687
TL
199 }
200 }
150cedd0
TL
201 }
202#endif
203
12c9957e
TL
204 /* If it's an expired lease, get rid of any bindings. */
205 if (lease -> ends < cur_time && lease -> scope.bindings)
4bd8800e 206 free_bindings (&lease -> scope, MDL);
12c9957e 207
ffdcd127
TL
208 /* Set the lease to really expire in 2 minutes, unless it has
209 not yet expired, in which case leave its expiry time alone. */
210 when = cur_time + 120;
211 if (when < lease -> ends)
212 when = lease -> ends;
213
5bc2e1f2 214 ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp);
20916cae
TL
215 out:
216 if (lease)
217 lease_dereference (&lease, MDL);
ed8bcd8f
TL
218}
219
5bc2e1f2 220void dhcprequest (packet, ms_nulltp)
ed8bcd8f 221 struct packet *packet;
5bc2e1f2 222 int ms_nulltp;
ed8bcd8f 223{
15c00bba 224 struct lease *lease;
b88e8e15 225 struct iaddr cip;
7a049f2c 226 struct subnet *subnet;
fa97acc1 227 int ours = 0;
5d25508c
TL
228 struct option_cache *oc;
229 struct data_string data;
230 int status;
d9eefc5d
TL
231 char msgbuf [1024]; /* XXX */
232 char *s;
5d25508c 233
951323fe 234 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
235 DHO_DHCP_REQUESTED_ADDRESS);
236 memset (&data, 0, sizeof data);
237 if (oc &&
ca1c700e
TL
238 evaluate_option_cache (&data, packet, (struct lease *)0,
239 packet -> options, (struct option_state *)0,
12c9957e 240 &global_scope, oc, MDL)) {
b88e8e15 241 cip.len = 4;
5d25508c 242 memcpy (cip.iabuf, data.data, 4);
4bd8800e 243 data_string_forget (&data, MDL);
a8b53b42 244 } else {
5d25508c 245 oc = (struct option_cache *)0;
a8b53b42
TL
246 cip.len = 4;
247 memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
248 }
249
15c00bba
TL
250 /* Find the lease that matches the address requested by the
251 client. */
44b2e3ad 252
20916cae
TL
253 subnet = (struct subnet *)0;
254 lease = (struct lease *)0;
255 if (find_subnet (&subnet, cip, MDL))
256 find_lease (&lease, packet,
257 subnet -> shared_network, &ours, MDL);
15c00bba 258
d9eefc5d
TL
259 if (lease && lease -> client_hostname &&
260 db_printable (lease -> client_hostname))
261 s = lease -> client_hostname;
262 else
263 s = (char *)0;
264
265 /* Say what we're doing... */
fdd46b53 266 sprintf (msgbuf, "DHCPREQUEST for %s from %s %s%s%svia %s",
c4924529 267 piaddr (cip),
d9eefc5d
TL
268 (packet -> raw -> htype
269 ? print_hw_addr (packet -> raw -> htype,
270 packet -> raw -> hlen,
fdd46b53 271 packet -> raw -> chaddr)
d9eefc5d
TL
272 : (lease
273 ? print_hex_1 (lease -> uid_len, lease -> uid,
274 lease -> uid_len)
275 : "<no identifier>")),
276 s ? "(" : "", s ? s : "", s ? ") " : "",
277 packet -> raw -> giaddr.s_addr
c4924529 278 ? inet_ntoa (packet -> raw -> giaddr)
d9eefc5d 279 : packet -> interface -> name);
a69f4fd3 280
44b2e3ad
TL
281 /* If a client on a given network REQUESTs a lease on an
282 address on a different network, NAK it. If the Requested
283 Address option was used, the protocol says that it must
284 have been broadcast, so we can trust the source network
285 information.
15c00bba
TL
286
287 If ciaddr was specified and Requested Address was not, then
288 we really only know for sure what network a packet came from
289 if it came through a BOOTP gateway - if it came through an
164f9c7e
TL
290 IP router, we can't respond. However, a client in REBINDING
291 state with the wrong IP address will also look like this, and
292 this is more likely, so we NAK these packets - if the packet
293 came through a router, the NAK won't reach the client anyway.
15c00bba 294
44b2e3ad
TL
295 If we don't think we know where the packet came from, it
296 came through a gateway from an unknown network, so it's not
297 from a RENEWING client. If we recognize the network it
298 *thinks* it's on, we can NAK it even though we don't
299 recognize the network it's *actually* on; otherwise we just
300 have to ignore it.
301
302 We don't currently try to take advantage of access to the
303 raw packet, because it's not available on all platforms.
304 So a packet that was unicast to us through a router from a
305 RENEWING client is going to look exactly like a packet that
306 was broadcast to us from an INIT-REBOOT client.
307
308 Since we can't tell the difference between these two kinds
309 of packets, if the packet appears to have come in off the
310 local wire, we have to treat it as if it's a RENEWING
311 client. This means that we can't NAK a RENEWING client on
312 the local wire that has a bogus address. The good news is
313 that we won't ACK it either, so it should revert to INIT
314 state and send us a DHCPDISCOVER, which we *can* work with.
315
316 Because we can't detect that a RENEWING client is on the
317 wrong wire, it's going to sit there trying to renew until
318 it gets to the REBIND state, when we *can* NAK it because
319 the packet will get to us through a BOOTP gateway. We
320 shouldn't actually see DHCPREQUEST packets from RENEWING
321 clients on the wrong wire anyway, since their idea of their
322 local router will be wrong. In any case, the protocol
323 doesn't really allow us to NAK a DHCPREQUEST from a
324 RENEWING client, so we can punt on this issue. */
325
326 if (!packet -> shared_network ||
327 (packet -> raw -> ciaddr.s_addr &&
15c00bba 328 packet -> raw -> giaddr.s_addr) ||
164f9c7e 329 (!oc && packet -> raw -> ciaddr.s_addr) ||
10553ccb 330 (oc && !packet -> raw -> ciaddr.s_addr)) {
15c00bba
TL
331
332 /* If we don't know where it came from but we do know
333 where it claims to have come from, it didn't come
334 from there. Fry it. */
335 if (!packet -> shared_network) {
027f46cb 336 if (subnet && subnet -> group -> authoritative) {
8ae2d595 337 log_info ("%s: wrong network.", msgbuf);
15c00bba
TL
338 nak_lease (packet, &cip);
339 return;
340 }
4fbcd991 341 /* Otherwise, ignore it. */
e89a5afe 342 log_info ("%s: ignored (not authoritative).", msgbuf);
20916cae 343 goto out;
b88e8e15 344 }
15c00bba 345
44b2e3ad
TL
346 /* If we do know where it came from and it asked for an
347 address that is not on that shared network, nak it. */
20916cae
TL
348 if (subnet)
349 subnet_dereference (&subnet, MDL);
350 if (!find_grouped_subnet (&subnet, packet -> shared_network,
351 cip, MDL)) {
027f46cb
TL
352 if (packet -> shared_network -> group -> authoritative)
353 {
8ae2d595 354 log_info ("%s: wrong network.", msgbuf);
027f46cb 355 nak_lease (packet, &cip);
eeea1395 356 return;
027f46cb 357 }
e89a5afe 358 log_info ("%s: ignored (not authoritative).", msgbuf);
b88e8e15
TL
359 return;
360 }
361 }
ed8bcd8f 362
f39c1b92
TL
363#if defined (FAILOVER_PROTOCOL)
364 /* If we found a lease, but it belongs to a failover peer, and
365 the client is in the SELECTING state, ignore the request -
366 it's not ours. */
367 if (lease && (lease -> flags & PEER_IS_OWNER) &&
368 lookup_option (&dhcp_universe, packet -> options,
369 DHO_DHCP_SERVER_IDENTIFIER)) {
370 log_info ("%s: ignored (not for me)", msgbuf);
20916cae 371 goto out;
f39c1b92
TL
372 }
373
374 /* If we found a lease, but it belongs to a failover peer, and
375 we are communicating with that peer, drop it. This really
376 shouldn't happen - if the peer is up, it should have renewed
377 the client while the client was in the RENEWING state. However,
378 there are cases where the client won't be able to get unicast
379 packets to its server, but will be able to get broadcast packets
380 to its server, so for now I'm taking that possibility into
381 account, although this should be revisited later. Oh, also if
382 the client comes up in the REBINDING state, we'll see it here,
383 and shouldn't respond until its server has had a chance at it. */
384 if (lease && (lease -> flags & PEER_IS_OWNER) &&
385 lease -> pool && lease -> pool -> failover_peer &&
386 lease -> pool -> failover_peer -> my_state == normal) {
387 log_info ("%s: ignored (not for me)", msgbuf);
20916cae 388 goto out;
f39c1b92
TL
389 }
390#endif /* FAILOVER_PROTOCOL */
391
0c11afbc
TL
392 /* If the address the client asked for is ours, but it wasn't
393 available for the client, NAK it. */
394 if (!lease && ours) {
8ae2d595 395 log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
0c11afbc 396 nak_lease (packet, &cip);
20916cae 397 goto out;
0c11afbc
TL
398 }
399
6dadd610 400 /* Otherwise, send the lease to the client if we found one. */
eeea1395 401 if (lease) {
5bc2e1f2 402 ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp);
eeea1395 403 } else
74f45f96 404 log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
20916cae
TL
405
406 out:
407 if (subnet)
408 subnet_dereference (&subnet, MDL);
409 if (lease)
410 lease_dereference (&lease, MDL);
411 return;
ed8bcd8f
TL
412}
413
5bc2e1f2 414void dhcprelease (packet, ms_nulltp)
ed8bcd8f 415 struct packet *packet;
5bc2e1f2 416 int ms_nulltp;
ed8bcd8f 417{
20916cae 418 struct lease *lease = (struct lease *)0;
2b260752 419 struct iaddr cip;
5d25508c
TL
420 struct option_cache *oc;
421 struct data_string data;
fdd46b53 422 char *s;
fa97acc1 423
2ba8b7cd
TL
424 /* DHCPRELEASE must not specify address in requested-address
425 option, but old protocol specs weren't explicit about this,
426 so let it go. */
951323fe 427 if ((oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c 428 DHO_DHCP_REQUESTED_ADDRESS))) {
8ae2d595 429 log_info ("DHCPRELEASE from %s specified requested-address.",
2ba8b7cd
TL
430 print_hw_addr (packet -> raw -> htype,
431 packet -> raw -> hlen,
432 packet -> raw -> chaddr));
fa97acc1
TL
433 }
434
951323fe 435 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
436 DHO_DHCP_CLIENT_IDENTIFIER);
437 memset (&data, 0, sizeof data);
438 if (oc &&
ca1c700e
TL
439 evaluate_option_cache (&data, packet, (struct lease *)0,
440 packet -> options, (struct option_state *)0,
12c9957e 441 &global_scope, oc, MDL)) {
20916cae 442 find_lease_by_uid (&lease, data.data, data.len, MDL);
4bd8800e 443 data_string_forget (&data, MDL);
ed8bcd8f 444
73a4b6e5
TL
445 /* See if we can find a lease that matches the IP address
446 the client is claiming. */
447 for (; lease; lease = lease -> n_uid) {
448 if (!memcmp (&packet -> raw -> ciaddr,
449 lease -> ip_addr.iabuf, 4)) {
450 break;
451 }
452 }
20916cae 453 }
12c9957e
TL
454
455 /* The client is supposed to pass a valid client-identifier,
456 but the spec on this has changed historically, so try the
457 IP address in ciaddr if the client-identifier fails. */
458 if (!lease) {
db2ed553
TL
459 cip.len = 4;
460 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
20916cae 461 find_lease_by_ip_addr (&lease, cip, MDL);
2ba8b7cd
TL
462 }
463
464
d9eefc5d
TL
465 if (lease && lease -> client_hostname &&
466 db_printable (lease -> client_hostname))
467 s = lease -> client_hostname;
468 else
469 s = (char *)0;
470
471 /* Say what we're doing... */
472 log_info ("DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
473 inet_ntoa (packet -> raw -> ciaddr),
474 (packet -> raw -> htype
475 ? print_hw_addr (packet -> raw -> htype,
f9a32ee9 476 packet -> raw -> hlen,
fdd46b53 477 packet -> raw -> chaddr)
d9eefc5d
TL
478 : (lease
479 ? print_hex_1 (lease -> uid_len, lease -> uid,
480 lease -> uid_len)
481 : "<no identifier>")),
482 s ? "(" : "", s ? s : "", s ? ") " : "",
483 packet -> raw -> giaddr.s_addr
484 ? inet_ntoa (packet -> raw -> giaddr)
485 : packet -> interface -> name,
486 lease ? "" : "not ");
a8b53b42 487
b88e8e15 488 /* If we found a lease, release it. */
20916cae 489 if (lease && lease -> ends > cur_time) {
43f23dcc 490 release_lease (lease, packet);
20916cae
TL
491 lease_dereference (&lease, MDL);
492 }
ed8bcd8f
TL
493}
494
5bc2e1f2 495void dhcpdecline (packet, ms_nulltp)
b88e8e15 496 struct packet *packet;
5bc2e1f2 497 int ms_nulltp;
b88e8e15 498{
20916cae 499 struct lease *lease = (struct lease *)0;
a8b53b42 500 struct iaddr cip;
5d25508c
TL
501 struct option_cache *oc;
502 struct data_string data;
19654922
TL
503 struct option_state *options = (struct option_state *)0;
504 int ignorep;
505 int i;
506 const char *status;
d9eefc5d 507 char *s;
a8b53b42 508
fa97acc1 509 /* DHCPDECLINE must specify address. */
951323fe 510 if (!(oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
511 DHO_DHCP_REQUESTED_ADDRESS)))
512 return;
513 memset (&data, 0, sizeof data);
ca1c700e
TL
514 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
515 packet -> options,
516 (struct option_state *)0,
12c9957e 517 &global_scope, oc, MDL))
fa97acc1 518 return;
a8b53b42 519
fa97acc1 520 cip.len = 4;
5d25508c 521 memcpy (cip.iabuf, data.data, 4);
4bd8800e 522 data_string_forget (&data, MDL);
20916cae 523 find_lease_by_ip_addr (&lease, cip, MDL);
fa97acc1 524
4bd8800e 525 option_state_allocate (&options, MDL);
a69f4fd3 526
19654922
TL
527 /* Execute statements in scope starting with the subnet scope. */
528 if (lease)
529 execute_statements_in_scope (packet, (struct lease *)0,
12c9957e
TL
530 packet -> options, options,
531 &global_scope,
532 lease -> subnet -> group,
19654922
TL
533 (struct group *)0);
534
535 /* Execute statements in the class scopes. */
536 for (i = packet -> class_count; i > 0; i--) {
537 execute_statements_in_scope
12c9957e
TL
538 (packet, (struct lease *)0, packet -> options, options,
539 &global_scope, packet -> classes [i - 1] -> group,
19654922 540 lease ? lease -> subnet -> group : (struct group *)0);
b88e8e15 541 }
19654922
TL
542
543 /* Drop the request if dhcpdeclines are being ignored. */
544 oc = lookup_option (&server_universe, options, SV_DECLINES);
545 if (!oc ||
12c9957e
TL
546 evaluate_boolean_option_cache (&ignorep, packet, lease,
547 packet -> options, options,
548 &lease -> scope, oc, MDL)) {
19654922
TL
549 /* If we found a lease, mark it as unusable and complain. */
550 if (lease) {
551 abandon_lease (lease, "declined.");
552 status = "";
553 }
554 status = " (not found)";
555 } else
556 status = " (ignored)";
557
d9eefc5d
TL
558 if (!ignorep) {
559 char *s;
560 if (lease && lease -> client_hostname &&
561 db_printable (lease -> client_hostname))
562 s = lease -> client_hostname;
563 else
564 s = (char *)0;
565
566 log_info ("DHCPDECLINE of %s from %s %s%s%svia %s %s",
19654922 567 piaddr (cip),
d9eefc5d
TL
568 (packet -> raw -> htype
569 ? print_hw_addr (packet -> raw -> htype,
570 packet -> raw -> hlen,
fdd46b53 571 packet -> raw -> chaddr)
d9eefc5d
TL
572 : (lease
573 ? print_hex_1 (lease -> uid_len, lease -> uid,
574 lease -> uid_len)
575 : "<no identifier>")),
576 s ? "(" : "", s ? s : "", s ? ") " : "",
19654922
TL
577 packet -> raw -> giaddr.s_addr
578 ? inet_ntoa (packet -> raw -> giaddr)
d9eefc5d
TL
579 : packet -> interface -> name,
580 status);
fdd46b53 581 }
19654922 582
4bd8800e 583 option_state_dereference (&options, MDL);
20916cae
TL
584 if (lease)
585 lease_dereference (&lease, MDL);
b88e8e15
TL
586}
587
5bc2e1f2 588void dhcpinform (packet, ms_nulltp)
b88e8e15 589 struct packet *packet;
5bc2e1f2 590 int ms_nulltp;
b88e8e15 591{
e77892f5
TL
592 char msgbuf [1024];
593 struct data_string d1, prl;
594 struct option_cache *oc;
595 struct expression *expr;
596 struct option_state *options = (struct option_state *)0;
597 struct dhcp_packet raw;
598 struct packet outgoing;
3175ee90 599 unsigned char dhcpack = DHCPACK;
20916cae 600 struct subnet *subnet = (struct subnet *)0;
e77892f5 601 struct iaddr cip;
b1b7b521
TL
602 unsigned i, j;
603 int nulltp;
e77892f5
TL
604 struct sockaddr_in to;
605 struct in_addr from;
606
cdc336ab
TL
607 /* The client should set ciaddr to its IP address, but apparently
608 it's common for clients not to do this, so we'll use their IP
609 source address if they didn't set ciaddr. */
610 if (!packet -> raw -> ciaddr.s_addr) {
611 cip.len = 4;
612 memcpy (cip.iabuf, &packet -> client_addr, 4);
613 } else {
614 cip.len = 4;
615 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
616 }
617
e77892f5 618 sprintf (msgbuf, "DHCPINFORM from %s via %s",
cdc336ab
TL
619 piaddr (cip), packet -> interface -> name);
620
621 /* If the IP source address is zero, don't respond. */
622 if (!memcmp (cip.iabuf, "\0\0\0", 4)) {
e89a5afe 623 log_info ("%s: ignored (null source address).", msgbuf);
cdc336ab
TL
624 return;
625 }
e77892f5
TL
626
627 /* Find the subnet that the client is on. */
628 oc = (struct option_cache *)0;
20916cae 629 find_subnet (&subnet , cip, MDL);
e77892f5
TL
630
631 /* Sourceless packets don't make sense here. */
632 if (!subnet) {
633 log_info ("%s: unknown subnet %s",
634 msgbuf, inet_ntoa (packet -> raw -> giaddr));
e77892f5
TL
635 }
636
e89a5afe
TL
637 /* We don't respond to DHCPINFORM packets if we're not authoritative.
638 It would be nice if a per-host value could override this, but
639 there's overhead involved in checking this, so let's see how people
640 react first. */
c398d02c 641 if (subnet && !subnet -> group -> authoritative) {
20916cae 642 static int eso = 0;
e89a5afe
TL
643 log_info ("%s: not authoritative for subnet %s",
644 msgbuf, piaddr (subnet -> net));
20916cae
TL
645 if (!eso) {
646 log_info ("If this DHCP server is authoritative for%s",
647 " that subnet,");
648 log_info ("please write an `authoritative;' directi%s",
649 "ve either in the");
650 log_info ("subnet declaration or in some scope that%s",
651 "encloses the");
652 log_info ("subnet declaration - for example, write %s",
653 "it at the top");
654 log_info ("of the dhcpd.conf file.");
655 }
656 if (eso++ == 100)
657 eso = 0;
658 subnet_dereference (&subnet, MDL);
e89a5afe
TL
659 return;
660 }
661
e77892f5 662 memset (&d1, 0, sizeof d1);
4bd8800e 663 option_state_allocate (&options, MDL);
e77892f5
TL
664 memset (&outgoing, 0, sizeof outgoing);
665 memset (&raw, 0, sizeof raw);
666 outgoing.raw = &raw;
667
668 /* Execute statements in scope starting with the subnet scope. */
10553ccb 669 if (subnet)
da38df14 670 execute_statements_in_scope (packet, (struct lease *)0,
12c9957e
TL
671 packet -> options, options,
672 &global_scope, subnet -> group,
10553ccb 673 (struct group *)0);
e77892f5
TL
674
675 /* Execute statements in the class scopes. */
676 for (i = packet -> class_count; i > 0; i--) {
677 execute_statements_in_scope
12c9957e
TL
678 (packet, (struct lease *)0, packet -> options, options,
679 &global_scope, packet -> classes [i - 1] -> group,
10553ccb 680 subnet ? subnet -> group : (struct group *)0);
e77892f5
TL
681 }
682
683 /* Figure out the filename. */
cdc336ab 684 memset (&d1, 0, sizeof d1);
e77892f5 685 oc = lookup_option (&server_universe, options, SV_FILENAME);
ca1c700e
TL
686 if (oc &&
687 evaluate_option_cache (&d1, packet, (struct lease *)0,
688 packet -> options, (struct option_state *)0,
12c9957e 689 &global_scope, oc, MDL)) {
e77892f5
TL
690 i = d1.len;
691 if (i > sizeof raw.file)
692 i = sizeof raw.file;
693 else
694 raw.file [i] = 0;
695 memcpy (raw.file, d1.data, i);
4bd8800e 696 data_string_forget (&d1, MDL);
e77892f5
TL
697 }
698
699 /* Choose a server name as above. */
10553ccb 700 oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
ca1c700e
TL
701 if (oc &&
702 evaluate_option_cache (&d1, packet, (struct lease *)0,
703 packet -> options, (struct option_state *)0,
12c9957e 704 &global_scope, oc, MDL)) {
e77892f5
TL
705 i = d1.len;
706 if (i > sizeof raw.sname)
707 i = sizeof raw.sname;
708 else
709 raw.sname [i] = 0;
710 memcpy (raw.sname, d1.data, i);
4bd8800e 711 data_string_forget (&d1, MDL);
e77892f5
TL
712 }
713
714 /* Set a flag if this client is a lame Microsoft client that NUL
715 terminates string options and expects us to do likewise. */
716 nulltp = 0;
717 if ((oc = lookup_option (&dhcp_universe, packet -> options,
718 DHO_HOST_NAME))) {
ca1c700e
TL
719 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
720 packet -> options, options,
12c9957e 721 &global_scope, oc, MDL)) {
e77892f5
TL
722 if (d1.data [d1.len - 1] == '\0')
723 nulltp = 1;
4bd8800e 724 data_string_forget (&d1, MDL);
e77892f5
TL
725 }
726 }
727
728 /* Put in DHCP-specific options. */
729 i = DHO_DHCP_MESSAGE_TYPE;
730 oc = (struct option_cache *)0;
4bd8800e 731 if (option_cache_allocate (&oc, MDL)) {
e77892f5
TL
732 if (make_const_data (&oc -> expression, &dhcpack, 1, 0, 0)) {
733 oc -> option = dhcp_universe.options [i];
734 save_option (&dhcp_universe, options, oc);
735 }
4bd8800e 736 option_cache_dereference (&oc, MDL);
e77892f5
TL
737 }
738
739 i = DHO_DHCP_SERVER_IDENTIFIER;
740 if (!(oc = lookup_option (&dhcp_universe, options, i))) {
741 use_primary:
742 oc = (struct option_cache *)0;
4bd8800e 743 if (option_cache_allocate (&oc, MDL)) {
e77892f5
TL
744 if (make_const_data
745 (&oc -> expression,
746 ((unsigned char *)
747 &packet -> interface -> primary_address),
748 sizeof packet -> interface -> primary_address,
749 0, 0)) {
750 oc -> option =
751 dhcp_universe.options [i];
752 save_option (&dhcp_universe,
753 options, oc);
754 }
4bd8800e 755 option_cache_dereference (&oc, MDL);
e77892f5
TL
756 }
757 from = packet -> interface -> primary_address;
758 } else {
ca1c700e 759 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
12c9957e
TL
760 packet -> options, options,
761 &global_scope, oc, MDL)) {
cdc336ab 762 if (!d1.len || d1.len != sizeof from) {
4bd8800e 763 data_string_forget (&d1, MDL);
e77892f5 764 goto use_primary;
cdc336ab 765 }
e77892f5 766 memcpy (&from, d1.data, sizeof from);
4bd8800e 767 data_string_forget (&d1, MDL);
e77892f5
TL
768 } else
769 goto use_primary;
770 }
771
772 /* Use the subnet mask from the subnet declaration if no other
773 mask has been provided. */
774 i = DHO_SUBNET_MASK;
10553ccb 775 if (subnet && !lookup_option (&dhcp_universe, options, i)) {
cdc336ab 776 oc = (struct option_cache *)0;
4bd8800e 777 if (option_cache_allocate (&oc, MDL)) {
e77892f5
TL
778 if (make_const_data (&oc -> expression,
779 subnet -> netmask.iabuf,
780 subnet -> netmask.len, 0, 0)) {
781 oc -> option = dhcp_universe.options [i];
782 save_option (&dhcp_universe, options, oc);
783 }
4bd8800e 784 option_cache_dereference (&oc, MDL);
e77892f5
TL
785 }
786 }
787
df598b3e
TL
788 /* Make an encapsulation for the NWIP suboptions if the client
789 asked for them. */
790 i = DHO_NWIP_SUBOPTIONS;
791 if (!lookup_option (&dhcp_universe, options, i)) {
792 oc = (struct option_cache *)0;
4bd8800e 793 if (option_cache_allocate (&oc, MDL)) {
df598b3e 794 memset (&d1, 0, sizeof d1);
fb6297b1 795 d1.data = (const unsigned char *)"nwip";
df598b3e
TL
796 d1.len = 4;
797 if (make_encapsulation (&oc -> expression, &d1)) {
798 oc -> option = dhcp_universe.options [i];
799 save_option (&dhcp_universe, options, oc);
800 }
4bd8800e 801 option_cache_dereference (&oc, MDL);
df598b3e
TL
802 }
803 }
804
e77892f5
TL
805 /* If we've been given a vendor option space, and there's something
806 in it, and we weren't given a vendor-encapsulated-options option,
807 then cons one up. */
808 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
809 j = SV_VENDOR_OPTION_SPACE;
810 if (!lookup_option (&dhcp_universe, options, i) &&
811 (oc = lookup_option (&server_universe, options, j)) &&
ca1c700e 812 evaluate_option_cache (&d1, packet, (struct lease *)0,
12c9957e
TL
813 packet -> options, options,
814 &global_scope, oc, MDL)) {
e77892f5 815 oc = (struct option_cache *)0;
4bd8800e 816 if (option_cache_allocate (&oc, MDL)) {
e77892f5
TL
817 if (make_encapsulation (&oc -> expression, &d1)) {
818 oc -> option = dhcp_universe.options [i];
819 save_option (&dhcp_universe, options, oc);
820 }
4bd8800e 821 option_cache_dereference (&oc, MDL);
e77892f5 822 }
4bd8800e 823 data_string_forget (&d1, MDL);
e77892f5
TL
824 }
825
10553ccb
TL
826 /* If a site option space has been specified, use that for
827 site option codes. */
828 i = SV_SITE_OPTION_SPACE;
0af446bc 829 if ((oc = lookup_option (&server_universe, options, i)) &&
ca1c700e 830 evaluate_option_cache (&d1, packet, (struct lease *)0,
12c9957e
TL
831 packet -> options, options,
832 &global_scope, oc, MDL)) {
20916cae 833 struct universe *u = (struct universe *)0;
10553ccb 834
20916cae
TL
835 if (!universe_hash_lookup (&u, universe_hash,
836 d1.data, d1.len, MDL)) {
10553ccb 837 log_error ("unknown option space %s.", d1.data);
4bd8800e 838 option_state_dereference (&options, MDL);
20916cae
TL
839 if (subnet)
840 subnet_dereference (&subnet, MDL);
10553ccb
TL
841 return;
842 }
843
844 options -> site_universe = u -> index;
845 options -> site_code_min = 128; /* XXX */
4bd8800e 846 data_string_forget (&d1, MDL);
10553ccb
TL
847 } else {
848 options -> site_universe = dhcp_universe.index;
849 options -> site_code_min = 0; /* Trust me, it works. */
850 }
851
cdc336ab 852 memset (&prl, 0, sizeof prl);
431693d1
TL
853
854 /* Use the parameter list from the scope if there is one. */
855 oc = lookup_option (&dhcp_universe, options,
e77892f5
TL
856 DHO_DHCP_PARAMETER_REQUEST_LIST);
857
431693d1
TL
858 /* Otherwise, if the client has provided a list of options
859 that it wishes returned, use it to prioritize. Otherwise,
860 prioritize based on the default priority list. */
861
cdc336ab 862 if (!oc)
431693d1 863 oc = lookup_option (&dhcp_universe, packet -> options,
cdc336ab
TL
864 DHO_DHCP_PARAMETER_REQUEST_LIST);
865
866 if (oc)
ca1c700e 867 evaluate_option_cache (&prl, packet, (struct lease *)0,
12c9957e
TL
868 packet -> options, options,
869 &global_scope, oc, MDL);
e77892f5
TL
870
871#ifdef DEBUG_PACKET
872 dump_packet (packet);
873 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
874#endif
875
876 log_info ("%s", msgbuf);
877
10553ccb
TL
878 /* Figure out the address of the boot file server. */
879 raw.siaddr = from;
880 if ((oc =
881 lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
ca1c700e 882 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
12c9957e
TL
883 packet -> options, options,
884 &global_scope, oc, MDL)) {
10553ccb
TL
885 /* If there was more than one answer,
886 take the first. */
887 if (d1.len >= 4 && d1.data)
888 memcpy (&raw.siaddr, d1.data, 4);
4bd8800e 889 data_string_forget (&d1, MDL);
10553ccb
TL
890 }
891 }
892
e77892f5
TL
893 /* Set up the option buffer... */
894 outgoing.packet_length =
da38df14 895 cons_options (packet, outgoing.raw, (struct lease *)0,
12c9957e
TL
896 0, packet -> options, options, &global_scope,
897 0, nulltp, 0,
e77892f5 898 prl.len ? &prl : (struct data_string *)0);
4bd8800e
TL
899 option_state_dereference (&options, MDL);
900 data_string_forget (&prl, MDL);
e77892f5
TL
901
902 /* Make sure that the packet is at least as big as a BOOTP packet. */
903 if (outgoing.packet_length < BOOTP_MIN_LEN)
904 outgoing.packet_length = BOOTP_MIN_LEN;
905
e77892f5 906 raw.giaddr = packet -> raw -> giaddr;
cdc336ab 907 raw.ciaddr = packet -> raw -> ciaddr;
e77892f5
TL
908 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
909 raw.hlen = packet -> raw -> hlen;
910 raw.htype = packet -> raw -> htype;
911
912 raw.xid = packet -> raw -> xid;
913 raw.secs = packet -> raw -> secs;
914 raw.flags = packet -> raw -> flags;
915 raw.hops = packet -> raw -> hops;
916 raw.op = BOOTREPLY;
917
918 /* Report what we're sending... */
919 log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));
920
921#ifdef DEBUG_PACKET
922 dump_packet (&outgoing);
923 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
924#endif
925
926 /* Set up the common stuff... */
927 to.sin_family = AF_INET;
928#ifdef HAVE_SA_LEN
929 to.sin_len = sizeof to;
930#endif
931 memset (to.sin_zero, 0, sizeof to.sin_zero);
932
71df44f5 933 /* Use the IP address we derived for the client. */
cdc336ab 934 memcpy (&to.sin_addr, cip.iabuf, 4);
e77892f5
TL
935 to.sin_port = remote_port;
936
937 errno = 0;
938 send_packet ((fallback_interface
939 ? fallback_interface : packet -> interface),
940 &outgoing, &raw, outgoing.packet_length,
941 from, &to, (struct hardware *)0);
20916cae
TL
942 if (subnet)
943 subnet_dereference (&subnet, MDL);
b88e8e15
TL
944}
945
a8b53b42 946void nak_lease (packet, cip)
ed8bcd8f 947 struct packet *packet;
a8b53b42 948 struct iaddr *cip;
ed8bcd8f
TL
949{
950 struct sockaddr_in to;
4fbcd991 951 struct in_addr from;
ed8bcd8f
TL
952 int result;
953 struct dhcp_packet raw;
954 unsigned char nak = DHCPNAK;
955 struct packet outgoing;
fde927d2 956 struct hardware hto;
20916cae 957 unsigned i;
5d25508c 958 struct data_string data;
951323fe 959 struct option_state *options = (struct option_state *)0;
5d25508c
TL
960 struct expression *expr;
961 struct option_cache *oc = (struct option_cache *)0;
20916cae 962 struct iaddr myfrom;
ed8bcd8f 963
4bd8800e 964 option_state_allocate (&options, MDL);
ed8bcd8f
TL
965 memset (&outgoing, 0, sizeof outgoing);
966 memset (&raw, 0, sizeof raw);
967 outgoing.raw = &raw;
968
969 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
4bd8800e 970 if (!option_cache_allocate (&oc, MDL)) {
8ae2d595 971 log_error ("No memory for DHCPNAK message type.");
4bd8800e 972 option_state_dereference (&options, MDL);
5d25508c
TL
973 return;
974 }
975 if (!make_const_data (&oc -> expression, &nak, sizeof nak, 0, 0)) {
8ae2d595 976 log_error ("No memory for expr_const expression.");
4bd8800e
TL
977 option_cache_dereference (&oc, MDL);
978 option_state_dereference (&options, MDL);
5d25508c
TL
979 return;
980 }
981 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];
951323fe 982 save_option (&dhcp_universe, options, oc);
4bd8800e 983 option_cache_dereference (&oc, MDL);
5d25508c 984
b88e8e15 985 /* Set DHCP_MESSAGE to whatever the message is */
4bd8800e 986 if (!option_cache_allocate (&oc, MDL)) {
8ae2d595 987 log_error ("No memory for DHCPNAK message type.");
4bd8800e 988 option_state_dereference (&options, MDL);
5d25508c
TL
989 return;
990 }
991 if (!make_const_data (&oc -> expression,
c5b0f529
TL
992 (unsigned char *)dhcp_message,
993 strlen (dhcp_message), 1, 0)) {
8ae2d595 994 log_error ("No memory for expr_const expression.");
4bd8800e
TL
995 option_cache_dereference (&oc, MDL);
996 option_state_dereference (&options, MDL);
5d25508c
TL
997 return;
998 }
999 oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];
951323fe 1000 save_option (&dhcp_universe, options, oc);
4bd8800e 1001 option_cache_dereference (&oc, MDL);
5d25508c 1002
20916cae
TL
1003 i = DHO_DHCP_SERVER_IDENTIFIER;
1004 if (!(oc = lookup_option (&dhcp_universe, options, i))) {
1005 use_primary:
1006 oc = (struct option_cache *)0;
1007 if (option_cache_allocate (&oc, MDL)) {
1008 if (make_const_data
1009 (&oc -> expression,
1010 ((unsigned char *)
1011 &packet -> interface -> primary_address),
1012 sizeof packet -> interface -> primary_address,
1013 0, 0)) {
1014 oc -> option =
1015 dhcp_universe.options [i];
1016 save_option (&dhcp_universe, options, oc);
1017 }
1018 option_cache_dereference (&oc, MDL);
1019 }
1020 myfrom.len = sizeof packet -> interface -> primary_address;
1021 memcpy (myfrom.iabuf,
1022 &packet -> interface -> primary_address, myfrom.len);
1023 } else {
1024 memset (&data, 0, sizeof data);
1025 if (evaluate_option_cache (&data, packet, (struct lease *)0,
1026 packet -> options, options,
1027 &global_scope, oc, MDL)) {
1028 if (!data.len ||
1029 data.len > sizeof myfrom.iabuf) {
1030 data_string_forget (&data, MDL);
1031 goto use_primary;
1032 }
1033 memcpy (myfrom.iabuf, data.data, data.len);
1034 myfrom.len = data.len;
1035 data_string_forget (&data, MDL);
1036 } else
1037 goto use_primary;
1038 }
1039
b88e8e15 1040 /* Do not use the client's requested parameter list. */
951323fe 1041 delete_option (&dhcp_universe, packet -> options,
5d25508c 1042 DHO_DHCP_PARAMETER_REQUEST_LIST);
b88e8e15 1043
ed8bcd8f 1044 /* Set up the option buffer... */
a4cb16ca 1045 outgoing.packet_length =
da38df14 1046 cons_options (packet, outgoing.raw, (struct lease *)0,
12c9957e
TL
1047 0, packet -> options, options, &global_scope,
1048 0, 0, 0, (struct data_string *)0);
4bd8800e 1049 option_state_dereference (&options, MDL);
ed8bcd8f 1050
b88e8e15 1051/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
801ecd88 1052 raw.siaddr = packet -> interface -> primary_address;
ed8bcd8f 1053 raw.giaddr = packet -> raw -> giaddr;
b88e8e15
TL
1054 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
1055 raw.hlen = packet -> raw -> hlen;
1056 raw.htype = packet -> raw -> htype;
ed8bcd8f
TL
1057
1058 raw.xid = packet -> raw -> xid;
1059 raw.secs = packet -> raw -> secs;
b88e8e15 1060 raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
ed8bcd8f
TL
1061 raw.hops = packet -> raw -> hops;
1062 raw.op = BOOTREPLY;
1063
7a049f2c 1064 /* Report what we're sending... */
8ae2d595 1065 log_info ("DHCPNAK on %s to %s via %s",
7a049f2c
TL
1066 piaddr (*cip),
1067 print_hw_addr (packet -> raw -> htype,
1068 packet -> raw -> hlen,
a69f4fd3
TL
1069 packet -> raw -> chaddr),
1070 packet -> raw -> giaddr.s_addr
1071 ? inet_ntoa (packet -> raw -> giaddr)
1072 : packet -> interface -> name);
1073
1074
7a049f2c
TL
1075
1076#ifdef DEBUG_PACKET
1077 dump_packet (packet);
1078 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
1079 dump_packet (&outgoing);
1080 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
1081#endif
1082
2cbc0e48 1083 hto.hbuf [0] = packet -> raw -> htype;
7a049f2c 1084 hto.hlen = packet -> raw -> hlen;
2cbc0e48
TL
1085 memcpy (&hto.hbuf [1], packet -> raw -> chaddr, hto.hlen);
1086 hto.hlen++;
7a049f2c
TL
1087
1088 /* Set up the common stuff... */
1089 to.sin_family = AF_INET;
1090#ifdef HAVE_SA_LEN
1091 to.sin_len = sizeof to;
1092#endif
1093 memset (to.sin_zero, 0, sizeof to.sin_zero);
1094
20916cae 1095 memcpy (&from, myfrom.iabuf, sizeof from);
4fbcd991 1096
11b37280
TL
1097 /* Make sure that the packet is at least as big as a BOOTP packet. */
1098 if (outgoing.packet_length < BOOTP_MIN_LEN)
1099 outgoing.packet_length = BOOTP_MIN_LEN;
1100
b88e8e15
TL
1101 /* If this was gatewayed, send it back to the gateway.
1102 Otherwise, broadcast it on the local network. */
1103 if (raw.giaddr.s_addr) {
ed8bcd8f 1104 to.sin_addr = raw.giaddr;
1b871100
TL
1105 if (raw.giaddr.s_addr != INADDR_LOOPBACK)
1106 to.sin_port = local_port;
1107 else
1108 to.sin_port = remote_port; /* for testing. */
7a049f2c 1109
027f46cb
TL
1110 if (fallback_interface) {
1111 result = send_packet (fallback_interface,
1112 packet, &raw,
1113 outgoing.packet_length,
1114 from, &to, &hto);
027f46cb
TL
1115 return;
1116 }
b88e8e15 1117 } else {
71df44f5 1118 to.sin_addr = limited_broadcast;
44b2e3ad 1119 to.sin_port = remote_port;
b88e8e15 1120 }
ed8bcd8f 1121
ed8bcd8f 1122 errno = 0;
fde927d2
TL
1123 result = send_packet (packet -> interface,
1124 packet, &raw, outgoing.packet_length,
4fbcd991 1125 from, &to, (struct hardware *)0);
ed8bcd8f
TL
1126}
1127
5bc2e1f2 1128void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
ed8bcd8f
TL
1129 struct packet *packet;
1130 struct lease *lease;
a7822eac 1131 unsigned int offer;
ed8bcd8f 1132 TIME when;
c4924529 1133 char *msg;
5bc2e1f2 1134 int ms_nulltp;
ed8bcd8f 1135{
20916cae 1136 struct lease *lt;
9cc3ad7f 1137 struct lease_state *state;
ed8bcd8f 1138 TIME lease_time;
4ecd2958 1139 TIME offered_lease_time;
b1dd98c9 1140 struct data_string d1;
eeea1395
TL
1141 TIME min_lease_time;
1142 TIME max_lease_time;
1143 TIME default_lease_time;
5d25508c
TL
1144 struct option_cache *oc;
1145 struct expression *expr;
1146 int status;
20916cae 1147 isc_result_t result;
ed8bcd8f 1148
b1b7b521
TL
1149 unsigned i, j;
1150 int s1, s2;
b1dd98c9 1151 int val;
19654922 1152 int ignorep;
b88e8e15 1153
9cc3ad7f 1154 /* If we're already acking this lease, don't do it again. */
c4924529 1155 if (lease -> state)
9cc3ad7f 1156 return;
9cc3ad7f 1157
a52d8045 1158 /* Allocate a lease state structure... */
4bd8800e 1159 state = new_lease_state (MDL);
a52d8045 1160 if (!state)
8ae2d595 1161 log_fatal ("unable to allocate lease state!");
cdc336ab 1162 state -> got_requested_address = packet -> got_requested_address;
20916cae
TL
1163 shared_network_reference (&state -> shared_network,
1164 packet -> interface -> shared_network, MDL);
cdc336ab
TL
1165
1166 /* See if we got a server identifier option. */
1167 if (lookup_option (&dhcp_universe,
1168 packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
1169 state -> got_server_identifier = 1;
a52d8045 1170
44b2e3ad 1171 /* Replace the old lease hostname with the new one, if it's changed. */
951323fe 1172 oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
5d25508c
TL
1173 memset (&d1, 0, sizeof d1);
1174 if (oc)
ca1c700e
TL
1175 s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
1176 packet -> options,
12c9957e
TL
1177 (struct option_state *)0,
1178 &global_scope, oc, MDL);
1179 if (oc && s1 &&
44b2e3ad 1180 lease -> client_hostname &&
5d25508c
TL
1181 strlen (lease -> client_hostname) == d1.len &&
1182 !memcmp (lease -> client_hostname, d1.data, d1.len)) {
1183 /* Hasn't changed. */
4bd8800e 1184 data_string_forget (&d1, MDL);
5d25508c 1185 } else if (oc && s1) {
44b2e3ad 1186 if (lease -> client_hostname)
4bd8800e 1187 dfree (lease -> client_hostname, MDL);
44b2e3ad 1188 lease -> client_hostname =
4bd8800e 1189 dmalloc (d1.len + 1, MDL);
44b2e3ad 1190 if (!lease -> client_hostname)
8ae2d595 1191 log_error ("no memory for client hostname.");
5d25508c
TL
1192 else {
1193 memcpy (lease -> client_hostname, d1.data, d1.len);
1194 lease -> client_hostname [d1.len] = 0;
1195 }
4bd8800e 1196 data_string_forget (&d1, MDL);
44b2e3ad 1197 } else if (lease -> client_hostname) {
4bd8800e 1198 dfree (lease -> client_hostname, MDL);
44b2e3ad
TL
1199 lease -> client_hostname = 0;
1200 }
1201
b1dd98c9 1202 /* Steal the agent options from the packet. */
951323fe
TL
1203 if (packet -> options -> universes [agent_universe.index]) {
1204 state -> options -> universes [agent_universe.index] =
1205 packet -> options -> universes [agent_universe.index];
1206 packet -> options -> universes [agent_universe.index] =
1207 (struct agent_options *)0;
b1dd98c9
TL
1208 }
1209
d9eefc5d
TL
1210 /* If we are offering a lease that is still currently valid, preserve
1211 the events. We need to do this because if the client does not
1212 REQUEST our offer, it will expire in 2 minutes, overriding the
1213 expire time in the currently in force lease. We want the expire
1214 events to be executed at that point. */
1215 if (lease -> ends <= cur_time && offer != DHCPOFFER) {
1216 /* Get rid of any old expiry or release statements - by
1217 executing the statements below, we will be inserting new
1218 ones if there are any to insert. */
1219 if (lease -> on_expiry)
1220 executable_statement_dereference (&lease -> on_expiry,
4bd8800e 1221 MDL);
d9eefc5d
TL
1222 if (lease -> on_commit)
1223 executable_statement_dereference (&lease -> on_commit,
4bd8800e 1224 MDL);
d9eefc5d
TL
1225 if (lease -> on_release)
1226 executable_statement_dereference (&lease -> on_release,
4bd8800e 1227 MDL);
d9eefc5d 1228 }
ed2529e5 1229
10553ccb 1230 /* Execute statements in scope starting with the subnet scope. */
da38df14
TL
1231 execute_statements_in_scope (packet, lease,
1232 packet -> options,
12c9957e 1233 state -> options, &lease -> scope,
cfb80b3c 1234 lease -> subnet -> group,
b1dd98c9
TL
1235 (struct group *)0);
1236
10553ccb
TL
1237 /* If the lease is from a pool, run the pool scope. */
1238 if (lease -> pool)
da38df14
TL
1239 execute_statements_in_scope (packet, lease,
1240 packet -> options,
12c9957e 1241 state -> options, &lease -> scope,
10553ccb
TL
1242 lease -> pool -> group,
1243 lease -> subnet -> group);
1244
1245 /* Execute statements from class scopes. */
fa661adb
TL
1246 for (i = packet -> class_count; i > 0; i--) {
1247 execute_statements_in_scope
da38df14 1248 (packet, lease, packet -> options, state -> options,
12c9957e 1249 &lease -> scope, packet -> classes [i - 1] -> group,
fa661adb
TL
1250 (lease -> pool
1251 ? lease -> pool -> group
1252 : lease -> subnet -> group));
b1dd98c9
TL
1253 }
1254
1255 /* If we have a host_decl structure, run the options associated
1256 with its group. */
1257 if (lease -> host)
da38df14 1258 execute_statements_in_scope (packet, lease, packet -> options,
12c9957e 1259 state -> options, &lease -> scope,
b1dd98c9 1260 lease -> host -> group,
74f45f96
TL
1261 (lease -> pool
1262 ? lease -> pool -> group
1263 : lease -> subnet -> group));
6c8a5472 1264
e8e6a30f
TL
1265 /* See if the client is only supposed to have one lease at a time,
1266 and if so, find its other leases and release them. We can only
1267 do this on DHCPREQUEST. It's a little weird to do this before
1268 looking at permissions, because the client might not actually
1269 _get_ a lease after we've done the permission check, but the
1270 assumption for this option is that the client has exactly one
1271 network interface, and will only ever remember one lease. So
1272 if it sends a DHCPREQUEST, and doesn't get the lease, it's already
1273 forgotten about its old lease, so we can too. */
3db5bf9c 1274 if (packet -> packet_type == DHCPREQUEST &&
e8e6a30f
TL
1275 (oc = lookup_option (&server_universe, state -> options,
1276 SV_ONE_LEASE_PER_CLIENT)) &&
19654922
TL
1277 evaluate_boolean_option_cache (&ignorep,
1278 packet, lease, packet -> options,
12c9957e
TL
1279 state -> options, &lease -> scope,
1280 oc, MDL)) {
e8e6a30f
TL
1281 struct lease *seek;
1282 if (lease -> uid_len) {
20916cae 1283 struct lease *s;
e8e6a30f 1284 do {
20916cae
TL
1285 seek = (struct lease *)0;
1286 find_lease_by_uid (&seek, lease -> uid,
1287 lease -> uid_len, MDL);
1288
15eda248
TL
1289 /* Don't release expired leases, and don't
1290 release the lease we're going to assign. */
20916cae
TL
1291 s = seek;
1292 while (s) {
1293 if (s != lease &&
1294 s -> ends > cur_time)
15eda248 1295 break;
20916cae 1296 s = s -> n_uid;
15eda248 1297 }
20916cae 1298 if (s) {
43f23dcc 1299 release_lease (seek, packet);
e8e6a30f 1300 }
20916cae
TL
1301 if (seek)
1302 lease_dereference (&seek, MDL);
1303 } while (s);
d846dd04
TL
1304 }
1305 if (!lease -> uid_len ||
1306 (lease -> host &&
1307 !lease -> host -> client_identifier.len &&
1308 (oc = lookup_option (&server_universe, state -> options,
1309 SV_DUPLICATES)) &&
19654922 1310 !evaluate_boolean_option_cache (&ignorep, packet, lease,
d846dd04 1311 packet -> options,
12c9957e
TL
1312 state -> options,
1313 &lease -> scope,
1314 oc, MDL))) {
20916cae 1315 struct lease *s;
e8e6a30f 1316 do {
20916cae
TL
1317 seek = (struct lease *)0;
1318 find_lease_by_hw_addr
1319 (&seek, lease -> hardware_addr.hbuf,
1320 lease -> hardware_addr.hlen, MDL);
1321 s = seek;
1322 while (s) {
1323 if (s != lease &&
1324 s -> ends > cur_time)
15eda248 1325 break;
20916cae 1326 s = s -> n_hw;
15eda248 1327 }
20916cae
TL
1328 if (s) {
1329 release_lease (s, packet);
e8e6a30f 1330 }
20916cae
TL
1331 if (seek)
1332 lease_dereference (&s, MDL);
1333 } while (s);
e8e6a30f
TL
1334 }
1335 }
1336
1337
b1dd98c9
TL
1338 /* Make sure this packet satisfies the configured minimum
1339 number of seconds. */
2540af04 1340 if (offer == DHCPOFFER &&
951323fe 1341 (oc = lookup_option (&server_universe, state -> options,
5d25508c 1342 SV_MIN_SECS))) {
ca1c700e
TL
1343 if (evaluate_option_cache (&d1, packet, lease,
1344 packet -> options, state -> options,
12c9957e 1345 &lease -> scope, oc, MDL)) {
5d25508c 1346 if (d1.len && packet -> raw -> secs < d1.data [0]) {
ab58ff49
TL
1347 log_info ("%s: %d secs < %d", msg,
1348 packet -> raw -> secs, d1.data [0]);
4bd8800e
TL
1349 data_string_forget (&d1, MDL);
1350 free_lease_state (state, MDL);
1351 static_lease_dereference (lease, MDL);
5d25508c
TL
1352 return;
1353 }
4bd8800e 1354 data_string_forget (&d1, MDL);
5d25508c
TL
1355 }
1356 }
1357
1358 /* Try to find a matching host declaration for this lease. */
1359 if (!lease -> host) {
1360 struct host_decl *hp;
1361
1362 /* Try to find a host_decl that matches the client
1363 identifier or hardware address on the packet, and
1364 has no fixed IP address. If there is one, hang
1365 it off the lease so that its option definitions
1366 can be used. */
951323fe 1367 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
1368 DHO_DHCP_CLIENT_IDENTIFIER);
1369 if (oc &&
ca1c700e
TL
1370 evaluate_option_cache (&d1, packet, lease,
1371 packet -> options, state -> options,
12c9957e 1372 &lease -> scope, oc, MDL)) {
20916cae
TL
1373 struct host_decl *h;
1374 hp = (struct host_decl *)0;
1375 find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
4bd8800e 1376 data_string_forget (&d1, MDL);
5d25508c 1377 if (!hp)
20916cae
TL
1378 find_hosts_by_haddr (&hp,
1379 packet -> raw -> htype,
1380 packet -> raw -> chaddr,
1381 packet -> raw -> hlen,
1382 MDL);
1383 for (h = hp; h; h = h -> n_ipaddr) {
1384 if (!h -> fixed_addr)
5d25508c
TL
1385 break;
1386 }
20916cae
TL
1387 if (h)
1388 host_reference (&lease -> host, hp, MDL);
1389 if (hp)
1390 host_dereference (&hp, MDL);
5d25508c
TL
1391 } else
1392 lease -> host = (struct host_decl *)0;
b1dd98c9
TL
1393 }
1394
ddb4c2ac
TL
1395 /* Drop the request if it's not allowed for this client. By
1396 default, unknown clients are allowed. */
b1dd98c9 1397 if (!lease -> host &&
951323fe 1398 (oc = lookup_option (&server_universe, state -> options,
ddb4c2ac 1399 SV_BOOT_UNKNOWN_CLIENTS)) &&
19654922
TL
1400 !evaluate_boolean_option_cache (&ignorep,
1401 packet, lease, packet -> options,
12c9957e
TL
1402 state -> options,
1403 &lease -> scope, oc, MDL)) {
19654922
TL
1404 if (!ignorep)
1405 log_info ("%s: unknown client", msg);
4bd8800e
TL
1406 free_lease_state (state, MDL);
1407 static_lease_dereference (lease, MDL);
ddb4c2ac 1408 return;
b1dd98c9
TL
1409 }
1410
1411 /* Drop the request if it's not allowed for this client. */
1412 if (!offer &&
951323fe 1413 (oc = lookup_option (&server_universe, state -> options,
ddb4c2ac 1414 SV_ALLOW_BOOTP)) &&
19654922
TL
1415 !evaluate_boolean_option_cache (&ignorep,
1416 packet, lease, packet -> options,
12c9957e
TL
1417 state -> options,
1418 &lease -> scope, oc, MDL)) {
19654922
TL
1419 if (!ignorep)
1420 log_info ("%s: bootp disallowed", msg);
4bd8800e
TL
1421 free_lease_state (state, MDL);
1422 static_lease_dereference (lease, MDL);
ddb4c2ac 1423 return;
b1dd98c9
TL
1424 }
1425
5d25508c 1426 /* Drop the request if booting is specifically denied. */
951323fe
TL
1427 oc = lookup_option (&server_universe, state -> options,
1428 SV_ALLOW_BOOTING);
5d25508c 1429 if (oc &&
19654922
TL
1430 !evaluate_boolean_option_cache (&ignorep,
1431 packet, lease, packet -> options,
12c9957e
TL
1432 state -> options,
1433 &lease -> scope, oc, MDL)) {
19654922 1434 if (!ignorep)
8ae2d595 1435 log_info ("%s: booting disallowed", msg);
4bd8800e
TL
1436 free_lease_state (state, MDL);
1437 static_lease_dereference (lease, MDL);
19654922 1438 return;
b1dd98c9
TL
1439 }
1440
c4924529
TL
1441 /* If we are configured to do per-class billing, do it. */
1442 if (have_billing_classes) {
1443
1444 /* See if the lease is currently being billed to a
1445 class, and if so, whether or not it can continue to
1446 be billed to that class. */
1447 if (lease -> billing_class) {
1448 for (i = 0; i < packet -> class_count; i++)
1449 if (packet -> classes [i] ==
1450 lease -> billing_class)
1451 break;
1452 if (i == packet -> class_count)
1453 unbill_class (lease, lease -> billing_class);
1454 }
1455
1456 /* If we don't have an active billing, see if we need
1457 one, and if we do, try to do so. */
1458 if (!lease -> billing_class) {
1459 for (i = 0; i < packet -> class_count; i++) {
0af446bc 1460 if (packet -> classes [i] -> lease_limit)
c4924529
TL
1461 break;
1462 }
0af446bc 1463 if (i != packet -> class_count) {
c4924529 1464 for (i = 0; i < packet -> class_count; i++)
0af446bc
TL
1465 if ((packet ->
1466 classes [i] -> lease_limit) &&
1467 bill_class (lease,
c4924529
TL
1468 packet -> classes [i]))
1469 break;
1470 if (i == packet -> class_count) {
74f45f96
TL
1471 log_info ("%s: no available billing",
1472 msg);
4bd8800e 1473 free_lease_state (state, MDL);
6c8a5472 1474 /* XXX probably not necessary: */
4bd8800e 1475 static_lease_dereference (lease, MDL);
c4924529
TL
1476 return;
1477 }
1478 }
1479 }
1480 }
1481
b1dd98c9 1482 /* Figure out the filename. */
951323fe 1483 oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
5d25508c 1484 if (oc)
ca1c700e
TL
1485 evaluate_option_cache (&state -> filename, packet, lease,
1486 packet -> options, state -> options,
12c9957e 1487 &lease -> scope, oc, MDL);
ed8bcd8f 1488
7a049f2c 1489 /* Choose a server name as above. */
951323fe
TL
1490 oc = lookup_option (&server_universe, state -> options,
1491 SV_SERVER_NAME);
5d25508c 1492 if (oc)
ca1c700e
TL
1493 evaluate_option_cache (&state -> server_name, packet, lease,
1494 packet -> options, state -> options,
12c9957e 1495 &lease -> scope, oc, MDL);
7a049f2c 1496
97ca1699
TL
1497 /* At this point, we have a lease that we can offer the client.
1498 Now we construct a lease structure that contains what we want,
1499 and call supersede_lease to do the right thing with it. */
20916cae
TL
1500 lt = (struct lease *)0;
1501 result = lease_allocate (&lt, MDL);
1502 if (result != ISC_R_SUCCESS) {
1503 log_info ("%s: can't allocate temporary lease structure: %s",
1504 msg, isc_result_totext (result));
1505 free_lease_state (state, MDL);
1506 static_lease_dereference (lease, MDL);
1507 return;
1508 }
1509
97ca1699
TL
1510 /* Use the ip address of the lease that we finally found in
1511 the database. */
20916cae 1512 lt -> ip_addr = lease -> ip_addr;
97ca1699
TL
1513
1514 /* Start now. */
20916cae 1515 lt -> starts = cur_time;
97ca1699 1516
7a049f2c
TL
1517 /* Figure out how long a lease to assign. If this is a
1518 dynamic BOOTP lease, its duration must be infinite. */
1519 if (offer) {
eeea1395 1520 default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
951323fe 1521 if ((oc = lookup_option (&server_universe, state -> options,
eeea1395 1522 SV_DEFAULT_LEASE_TIME))) {
ca1c700e 1523 if (evaluate_option_cache (&d1, packet, lease,
da38df14 1524 packet -> options,
12c9957e
TL
1525 state -> options,
1526 &lease -> scope, oc, MDL)) {
eeea1395
TL
1527 if (d1.len == sizeof (u_int32_t))
1528 default_lease_time =
1529 getULong (d1.data);
4bd8800e 1530 data_string_forget (&d1, MDL);
eeea1395
TL
1531 }
1532 }
1533
951323fe 1534 if ((oc = lookup_option (&dhcp_universe, packet -> options,
1ffcdd2a 1535 DHO_DHCP_LEASE_TIME)))
ca1c700e 1536 s1 = evaluate_option_cache (&d1, packet, lease,
da38df14 1537 packet -> options,
12c9957e
TL
1538 state -> options,
1539 &lease -> scope, oc, MDL);
1ffcdd2a
TL
1540 else
1541 s1 = 0;
5d25508c
TL
1542 if (s1 && d1.len == sizeof (u_int32_t)) {
1543 lease_time = getULong (d1.data);
4bd8800e 1544 data_string_forget (&d1, MDL);
7a049f2c 1545 } else {
daa1b24f 1546 if (s1)
4bd8800e 1547 data_string_forget (&d1, MDL);
eeea1395 1548 lease_time = default_lease_time;
7a049f2c
TL
1549 }
1550
daa1b24f
TL
1551 /* See if there's a maximum lease time. */
1552 max_lease_time = DEFAULT_MAX_LEASE_TIME;
1553 if ((oc = lookup_option (&server_universe, state -> options,
1554 SV_MAX_LEASE_TIME))) {
ca1c700e 1555 if (evaluate_option_cache (&d1, packet, lease,
daa1b24f 1556 packet -> options,
12c9957e
TL
1557 state -> options,
1558 &lease -> scope, oc, MDL)) {
daa1b24f
TL
1559 if (d1.len == sizeof (u_int32_t))
1560 max_lease_time =
1561 getULong (d1.data);
4bd8800e 1562 data_string_forget (&d1, MDL);
daa1b24f
TL
1563 }
1564 }
1565
10553ccb 1566 /* Enforce the maximum lease length. */
daa1b24f
TL
1567 if (lease_time < 0 /* XXX */
1568 || lease_time > max_lease_time)
10553ccb
TL
1569 lease_time = max_lease_time;
1570
eeea1395 1571 min_lease_time = DEFAULT_MIN_LEASE_TIME;
00855426
TL
1572 if (min_lease_time > max_lease_time)
1573 min_lease_time = max_lease_time;
1574
951323fe 1575 if ((oc = lookup_option (&server_universe, state -> options,
5d25508c 1576 SV_MIN_LEASE_TIME))) {
ca1c700e 1577 if (evaluate_option_cache (&d1, packet, lease,
da38df14 1578 packet -> options,
12c9957e
TL
1579 state -> options,
1580 &lease -> scope, oc, MDL)) {
5d25508c 1581 if (d1.len == sizeof (u_int32_t))
eeea1395 1582 min_lease_time = getULong (d1.data);
4bd8800e 1583 data_string_forget (&d1, MDL);
5d25508c 1584 }
421563ea
TL
1585 }
1586
eeea1395
TL
1587 if (lease_time < min_lease_time) {
1588 if (min_lease_time)
1589 lease_time = min_lease_time;
1590 else
1591 lease_time = default_lease_time;
1592 }
b1dd98c9 1593
2cbc0e48
TL
1594#if defined (FAILOVER_PROTOCOL)
1595 /* Okay, we know the lease duration. Now check the
1596 failover state, if any. */
20916cae 1597 if (lease -> pool && lease -> pool -> failover_peer) {
2cbc0e48
TL
1598 dhcp_failover_state_t *peer =
1599 lease -> pool -> failover_peer;
1600
1601 /* If the lease time we arrived at exceeds what
1602 the peer has, first update the peer. */
1603 /* XXX This may result in updates that only push
1604 XXX the peer's expiry time for this lease up
1605 XXX by a few seconds - think about this again
1606 XXX later. */
1607 if (cur_time + lease_time > lease -> tsfp) {
1608 /* Here we're assuming that if we don't have
1609 to update tstp, there's already an update
1610 queued. May want to revisit this. */
8c8e27c5 1611 if (cur_time + lease_time > lease -> tstp)
20916cae 1612 lt -> tstp = cur_time + lease_time;
8c8e27c5 1613
2cbc0e48
TL
1614 /* Now choose a lease time that is either
1615 MCLT, for a lease that's never before been
1616 assigned, or TSFP + MCLT for a lease that
1617 has.
1618 XXX Note that TSFP may be < cur_time.
1619 XXX What do we do in this case?
1620 XXX should the expiry timer on the lease
1621 XXX set tsfp and tstp to zero? */
1622 if (lease -> tsfp == 0)
1623 lease_time = peer -> mclt;
1624 else
1625 lease_time = (lease -> tsfp - cur_time
1626 + peer -> mclt);
1627 }
20916cae 1628 lt -> cltt = cur_time;
2cbc0e48
TL
1629 }
1630#endif /* FAILOVER_PROTOCOL */
1631
00855426
TL
1632 /* If the lease duration causes the time value to wrap,
1633 use the maximum expiry time. */
1634 if (cur_time + lease_time < cur_time)
1635 state -> offered_expiry = MAX_TIME;
1636 else
1637 state -> offered_expiry = cur_time + lease_time;
7a049f2c 1638 if (when)
20916cae 1639 lt -> ends = when;
7a049f2c 1640 else
20916cae 1641 lt -> ends = state -> offered_expiry;
7a049f2c 1642 } else {
b1dd98c9
TL
1643 lease_time = MAX_TIME - cur_time;
1644
951323fe 1645 if ((oc = lookup_option (&server_universe, state -> options,
5d25508c 1646 SV_BOOTP_LEASE_LENGTH))) {
ca1c700e
TL
1647 if (evaluate_option_cache (&d1, packet, lease,
1648 packet -> options,
1649 state -> options,
12c9957e 1650 &lease -> scope, oc, MDL)) {
5d25508c
TL
1651 if (d1.len == sizeof (u_int32_t))
1652 lease_time = getULong (d1.data);
4bd8800e 1653 data_string_forget (&d1, MDL);
5d25508c 1654 }
b1dd98c9
TL
1655 }
1656
951323fe 1657 if ((oc = lookup_option (&server_universe, state -> options,
5d25508c 1658 SV_BOOTP_LEASE_CUTOFF))) {
ca1c700e 1659 if (evaluate_option_cache (&d1, packet, lease,
da38df14 1660 packet -> options,
ca1c700e 1661 state -> options,
12c9957e 1662 &lease -> scope, oc, MDL)) {
5d25508c
TL
1663 if (d1.len == sizeof (u_int32_t))
1664 lease_time = (getULong (d1.data) -
1665 cur_time);
4bd8800e 1666 data_string_forget (&d1, MDL);
5d25508c 1667 }
b1dd98c9
TL
1668 }
1669
20916cae
TL
1670 lt -> ends = state -> offered_expiry = cur_time + lease_time;
1671 lt -> flags = BOOTP_LEASE;
7a049f2c 1672 }
97ca1699 1673
20916cae 1674 lt -> timestamp = cur_time;
97ca1699
TL
1675
1676 /* Record the uid, if given... */
951323fe 1677 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
1678 DHO_DHCP_CLIENT_IDENTIFIER);
1679 if (oc &&
ca1c700e 1680 evaluate_option_cache (&d1, packet, lease,
12c9957e
TL
1681 packet -> options, state -> options,
1682 &lease -> scope, oc, MDL)) {
20916cae
TL
1683 if (d1.len <= sizeof lt -> uid_buf) {
1684 memcpy (lt -> uid_buf, d1.data, d1.len);
1685 lt -> uid = lt -> uid_buf;
1686 lt -> uid_max = sizeof lt -> uid_buf;
1687 lt -> uid_len = d1.len;
11b37280 1688 } else {
b1b7b521 1689 unsigned char *tuid;
20916cae
TL
1690 lt -> uid_max = d1.len;
1691 lt -> uid_len = d1.len;
1692 tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);
5d25508c 1693 /* XXX inelegant */
b1b7b521 1694 if (!tuid)
951323fe 1695 log_fatal ("no memory for large uid.");
20916cae
TL
1696 memcpy (tuid, d1.data, lt -> uid_len);
1697 lt -> uid = tuid;
11b37280 1698 }
4bd8800e 1699 data_string_forget (&d1, MDL);
97ca1699
TL
1700 }
1701
20916cae
TL
1702 if (lease -> host)
1703 host_reference (&lt -> host, lease -> host, MDL);
1704 if (lease -> subnet)
1705 subnet_reference (&lt -> subnet, lease -> subnet, MDL);
1706 if (lease -> billing_class)
1707 class_reference (&lt -> billing_class,
1708 lease -> billing_class, MDL);
97ca1699 1709
9e0e9ed8
TL
1710 /* Set a flag if this client is a broken client that NUL
1711 terminates string options and expects us to do likewise. */
5bc2e1f2
TL
1712 if (ms_nulltp)
1713 lease -> flags |= MS_NULL_TERMINATION;
1714 else
8c8e27c5 1715 lease -> flags &= ~MS_NULL_TERMINATION;
9e0e9ed8 1716
6c8a5472
TL
1717 /* If there are statements to execute when the lease is
1718 committed, execute them. */
1719 if (lease -> on_commit && (!offer || offer == DHCPACK)) {
1720 execute_statements (packet, lease, packet -> options,
12c9957e
TL
1721 state -> options, &lease -> scope,
1722 lease -> on_commit);
1723 if (lease -> on_commit)
1724 executable_statement_dereference (&lease -> on_commit,
4bd8800e 1725 MDL);
6c8a5472
TL
1726 }
1727
12c9957e 1728 /* Save any bindings. */
20916cae 1729 lt -> scope.bindings = lease -> scope.bindings;
12c9957e
TL
1730 lease -> scope.bindings = (struct binding *)0;
1731
7a049f2c 1732 /* Don't call supersede_lease on a mocked-up lease. */
ec8d21a7
TL
1733 if (lease -> flags & STATIC_LEASE) {
1734 /* Copy the hardware address into the static lease
1735 structure. */
2cbc0e48
TL
1736 lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
1737 lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
1738 memcpy (&lease -> hardware_addr.hbuf [1],
1739 packet -> raw -> chaddr,
3c893bb6 1740 sizeof packet -> raw -> chaddr); /* XXX */
ec8d21a7
TL
1741 } else {
1742 /* Record the hardware address, if given... */
20916cae
TL
1743 lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
1744 lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
1745 memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
3c893bb6 1746 sizeof packet -> raw -> chaddr);
ec8d21a7
TL
1747
1748 /* Install the new information about this lease in the
1749 database. If this is a DHCPACK or a dynamic BOOTREPLY
1750 and we can't write the lease, don't ACK it (or BOOTREPLY
1751 it) either. */
1752
20916cae 1753 if (!(supersede_lease (lease, lt, !offer || offer == DHCPACK,
8c8e27c5 1754 offer == DHCPACK)
c4924529 1755 || (offer && offer != DHCPACK))) {
8ae2d595 1756 log_info ("%s: database update failed", msg);
4bd8800e
TL
1757 free_lease_state (state, MDL);
1758 static_lease_dereference (lease, MDL);
20916cae 1759 lease_dereference (&lt, MDL);
7a049f2c 1760 return;
d9eefc5d
TL
1761 } else {
1762 /* If this is a DHCPOFFER transaction, supersede_lease
1763 will not add the timer for the expire event to the
1764 queue. This is because DHCPOFFERS are not commited,
1765 and supersede_lease only adds commited leases to the
1766 timer queue. So if supersede_lease set this lease
1767 as the next one to expire for the pool we need to
1768 put it on the timer queue ourself. */
1769 /* XXX need to think about this. */
1770 if (offer == DHCPOFFER && lease -> pool &&
1771 lease -> pool -> next_expiry == lease)
1772 add_timeout (lease -> ends, pool_timer,
20916cae
TL
1773 lease -> pool,
1774 (tvref_t)omapi_object_reference,
1775 (tvunref_t)
1776 omapi_object_dereference);
c4924529 1777 }
ec8d21a7 1778 }
20916cae 1779 lease_dereference (&lt, MDL);
97ca1699 1780
11b37280 1781 /* Remember the interface on which the packet arrived. */
9cc3ad7f 1782 state -> ip = packet -> interface;
685963dc 1783
11b37280 1784 /* Remember the giaddr, xid, secs, flags and hops. */
9cc3ad7f 1785 state -> giaddr = packet -> raw -> giaddr;
44b2e3ad 1786 state -> ciaddr = packet -> raw -> ciaddr;
9cc3ad7f
TL
1787 state -> xid = packet -> raw -> xid;
1788 state -> secs = packet -> raw -> secs;
1789 state -> bootp_flags = packet -> raw -> flags;
1790 state -> hops = packet -> raw -> hops;
1791 state -> offer = offer;
685963dc 1792
6dadd610
TL
1793 /* If we're always supposed to broadcast to this client, set
1794 the broadcast bit in the bootp flags field. */
e3b5f7f8
TL
1795 if ((oc = lookup_option (&server_universe, state -> options,
1796 SV_ALWAYS_BROADCAST)) &&
19654922 1797 evaluate_boolean_option_cache (&ignorep, packet, lease,
ca1c700e 1798 packet -> options, state -> options,
12c9957e 1799 &lease -> scope, oc, MDL))
6dadd610
TL
1800 state -> bootp_flags |= htons (BOOTP_BROADCAST);
1801
3c893bb6
TL
1802 /* Get the Maximum Message Size option from the packet, if one
1803 was sent. */
951323fe 1804 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
1805 DHO_DHCP_MAX_MESSAGE_SIZE);
1806 if (oc &&
ca1c700e 1807 evaluate_option_cache (&d1, packet, lease,
12c9957e
TL
1808 packet -> options, state -> options,
1809 &lease -> scope, oc, MDL)) {
5d25508c
TL
1810 if (d1.len == sizeof (u_int16_t))
1811 state -> max_message_size = getUShort (d1.data);
4bd8800e 1812 data_string_forget (&d1, MDL);
3c893bb6
TL
1813 }
1814
7a049f2c
TL
1815 /* Now, if appropriate, put in DHCP-specific options that
1816 override those. */
9cc3ad7f 1817 if (state -> offer) {
11b37280 1818 i = DHO_DHCP_MESSAGE_TYPE;
5d25508c 1819 oc = (struct option_cache *)0;
4bd8800e 1820 if (option_cache_allocate (&oc, MDL)) {
5d25508c 1821 if (make_const_data (&oc -> expression,
e77892f5 1822 &state -> offer, 1, 0, 0)) {
5d25508c
TL
1823 oc -> option =
1824 dhcp_universe.options [i];
951323fe
TL
1825 save_option (&dhcp_universe,
1826 state -> options, oc);
5d25508c 1827 }
4bd8800e 1828 option_cache_dereference (&oc, MDL);
5d25508c 1829 }
11b37280 1830 i = DHO_DHCP_SERVER_IDENTIFIER;
951323fe
TL
1831 if (!(oc = lookup_option (&dhcp_universe,
1832 state -> options, i))) {
5d25508c
TL
1833 use_primary:
1834 oc = (struct option_cache *)0;
4bd8800e 1835 if (option_cache_allocate (&oc, MDL)) {
5d25508c
TL
1836 if (make_const_data
1837 (&oc -> expression,
1838 ((unsigned char *)
1839 &state -> ip -> primary_address),
1840 sizeof state -> ip -> primary_address,
1841 0, 0)) {
1842 oc -> option =
1843 dhcp_universe.options [i];
951323fe
TL
1844 save_option (&dhcp_universe,
1845 state -> options, oc);
5d25508c 1846 }
4bd8800e 1847 option_cache_dereference (&oc, MDL);
5d25508c
TL
1848 }
1849 state -> from.len =
1850 sizeof state -> ip -> primary_address;
1851 memcpy (state -> from.iabuf,
1852 &state -> ip -> primary_address,
1853 state -> from.len);
1854 } else {
ca1c700e 1855 if (evaluate_option_cache (&d1, packet, lease,
da38df14 1856 packet -> options,
12c9957e
TL
1857 state -> options,
1858 &lease -> scope, oc, MDL)) {
5d25508c 1859 if (!d1.len ||
cdc336ab 1860 d1.len > sizeof state -> from.iabuf) {
4bd8800e 1861 data_string_forget (&d1, MDL);
5d25508c 1862 goto use_primary;
cdc336ab 1863 }
5d25508c
TL
1864 memcpy (state -> from.iabuf, d1.data, d1.len);
1865 state -> from.len = d1.len;
4bd8800e 1866 data_string_forget (&d1, MDL);
5d25508c
TL
1867 } else
1868 goto use_primary;
421563ea 1869 }
7a049f2c 1870
b1dd98c9
TL
1871 offered_lease_time =
1872 state -> offered_expiry - cur_time;
b88e8e15 1873
9cc3ad7f 1874 putULong ((unsigned char *)&state -> expiry,
b1b7b521 1875 (unsigned long)offered_lease_time);
11b37280 1876 i = DHO_DHCP_LEASE_TIME;
951323fe 1877 if (lookup_option (&dhcp_universe, state -> options, i))
8ae2d595 1878 log_error ("dhcp-lease-time option for %s overridden.",
5941275a 1879 inet_ntoa (state -> ciaddr));
5d25508c 1880 oc = (struct option_cache *)0;
4bd8800e 1881 if (option_cache_allocate (&oc, MDL)) {
5d25508c
TL
1882 if (make_const_data (&oc -> expression,
1883 (unsigned char *)&state -> expiry,
1884 sizeof state -> expiry, 0, 0)) {
1885 oc -> option = dhcp_universe.options [i];
951323fe
TL
1886 save_option (&dhcp_universe,
1887 state -> options, oc);
5d25508c 1888 }
4bd8800e 1889 option_cache_dereference (&oc, MDL);
5d25508c 1890 }
7a049f2c 1891
4ecd2958
TL
1892 /* Renewal time is lease time * 0.5. */
1893 offered_lease_time /= 2;
9cc3ad7f 1894 putULong ((unsigned char *)&state -> renewal,
b1b7b521 1895 (unsigned long)offered_lease_time);
11b37280 1896 i = DHO_DHCP_RENEWAL_TIME;
951323fe
TL
1897 if (lookup_option (&dhcp_universe, state -> options, i))
1898 log_error ("overriding dhcp-renewal-time for %s.",
1899 inet_ntoa (state -> ciaddr));
5d25508c 1900 oc = (struct option_cache *)0;
4bd8800e 1901 if (option_cache_allocate (&oc, MDL)) {
5d25508c
TL
1902 if (make_const_data (&oc -> expression,
1903 (unsigned char *)
1904 &state -> renewal,
1905 sizeof state -> renewal, 0, 0)) {
1906 oc -> option = dhcp_universe.options [i];
951323fe
TL
1907 save_option (&dhcp_universe,
1908 state -> options, oc);
5d25508c 1909 }
4bd8800e 1910 option_cache_dereference (&oc, MDL);
5d25508c 1911 }
4ecd2958
TL
1912
1913 /* Rebinding time is lease time * 0.875. */
1914 offered_lease_time += (offered_lease_time / 2
1915 + offered_lease_time / 4);
9cc3ad7f 1916 putULong ((unsigned char *)&state -> rebind,
b1b7b521 1917 (unsigned)offered_lease_time);
11b37280 1918 i = DHO_DHCP_REBINDING_TIME;
951323fe
TL
1919 if (lookup_option (&dhcp_universe, state -> options, i))
1920 log_error ("overriding dhcp-rebinding-time for %s.",
5941275a 1921 inet_ntoa (state -> ciaddr));
5d25508c 1922 oc = (struct option_cache *)0;
4bd8800e 1923 if (option_cache_allocate (&oc, MDL)) {
5d25508c
TL
1924 if (make_const_data (&oc -> expression,
1925 (unsigned char *)&state -> rebind,
1926 sizeof state -> rebind, 0, 0)) {
1927 oc -> option = dhcp_universe.options [i];
951323fe
TL
1928 save_option (&dhcp_universe,
1929 state -> options, oc);
5d25508c 1930 }
4bd8800e 1931 option_cache_dereference (&oc, MDL);
5d25508c 1932 }
10553ccb
TL
1933 } else {
1934 state -> from.len =
1935 sizeof state -> ip -> primary_address;
1936 memcpy (state -> from.iabuf,
1937 &state -> ip -> primary_address,
1938 state -> from.len);
1939 }
1940
1941 /* Figure out the address of the boot file server. */
1942 memcpy (&state -> siaddr, state -> from.iabuf, sizeof state -> siaddr);
1943 if ((oc =
1944 lookup_option (&server_universe,
1945 state -> options, SV_NEXT_SERVER))) {
ca1c700e
TL
1946 if (evaluate_option_cache (&d1, packet, lease,
1947 packet -> options, state -> options,
12c9957e 1948 &lease -> scope, oc, MDL)) {
10553ccb
TL
1949 /* If there was more than one answer,
1950 take the first. */
1951 if (d1.len >= 4 && d1.data)
46904800 1952 memcpy (&state -> siaddr, d1.data, 4);
4bd8800e 1953 data_string_forget (&d1, MDL);
10553ccb 1954 }
7a049f2c 1955 }
685963dc 1956
4ecd2958
TL
1957 /* Use the subnet mask from the subnet declaration if no other
1958 mask has been provided. */
11b37280 1959 i = DHO_SUBNET_MASK;
951323fe 1960 if (!lookup_option (&dhcp_universe, state -> options, i)) {
4d0aaa17 1961 oc = (struct option_cache *)0;
4bd8800e 1962 if (option_cache_allocate (&oc, MDL)) {
5d25508c
TL
1963 if (make_const_data (&oc -> expression,
1964 lease -> subnet -> netmask.iabuf,
1965 lease -> subnet -> netmask.len,
1966 0, 0)) {
1967 oc -> option = dhcp_universe.options [i];
951323fe
TL
1968 save_option (&dhcp_universe,
1969 state -> options, oc);
5d25508c 1970 }
4bd8800e 1971 option_cache_dereference (&oc, MDL);
5d25508c 1972 }
b1dd98c9
TL
1973 }
1974
1975 /* Use the hostname from the host declaration if there is one
1976 and no hostname has otherwise been provided, and if the
1977 use-host-decl-name flag is set. */
1978 i = DHO_HOST_NAME;
5d25508c 1979 j = SV_USE_HOST_DECL_NAMES;
951323fe 1980 if (!lookup_option (&dhcp_universe, state -> options, i) &&
5d25508c
TL
1981 lease -> host && lease -> host -> name &&
1982 (evaluate_boolean_option_cache
19654922 1983 (&ignorep, packet, lease, packet -> options, state -> options,
12c9957e
TL
1984 &lease -> scope,
1985 lookup_option (&server_universe, state -> options, j), MDL))) {
5d25508c 1986 oc = (struct option_cache *)0;
4bd8800e 1987 if (option_cache_allocate (&oc, MDL)) {
5d25508c 1988 if (make_const_data (&oc -> expression,
c5b0f529
TL
1989 ((unsigned char *)
1990 lease -> host -> name),
5d25508c
TL
1991 strlen (lease -> host -> name),
1992 1, 0)) {
1993 oc -> option = dhcp_universe.options [i];
951323fe
TL
1994 save_option (&dhcp_universe,
1995 state -> options, oc);
5d25508c 1996 }
4bd8800e 1997 option_cache_dereference (&oc, MDL);
b1dd98c9
TL
1998 }
1999 }
2000
2001 /* If we don't have a hostname yet, and we've been asked to do
2002 a reverse lookup to find the hostname, do it. */
5d25508c 2003 j = SV_GET_LEASE_HOSTNAMES;
0af446bc 2004 if (!lookup_option (&server_universe, state -> options, i) &&
5d25508c 2005 (evaluate_boolean_option_cache
19654922 2006 (&ignorep, packet, lease, packet -> options, state -> options,
12c9957e
TL
2007 &lease -> scope, lookup_option (&server_universe,
2008 state -> options, j), MDL))) {
5d25508c
TL
2009 struct in_addr ia;
2010 struct hostent *h;
2011
2012 memcpy (&ia, lease -> ip_addr.iabuf, 4);
2013
2014 h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
2015 if (!h)
8ae2d595 2016 log_error ("No hostname for %s", inet_ntoa (ia));
5d25508c
TL
2017 else {
2018 oc = (struct option_cache *)0;
4bd8800e 2019 if (option_cache_allocate (&oc, MDL)) {
5d25508c 2020 if (make_const_data (&oc -> expression,
c5b0f529
TL
2021 ((unsigned char *)
2022 h -> h_name),
5d25508c
TL
2023 strlen (h -> h_name) + 1,
2024 1, 1)) {
2025 oc -> option =
2026 dhcp_universe.options [i];
951323fe
TL
2027 save_option (&dhcp_universe,
2028 state -> options, oc);
5d25508c 2029 }
4bd8800e 2030 option_cache_dereference (&oc, MDL);
b1dd98c9
TL
2031 }
2032 }
4ecd2958
TL
2033 }
2034
421563ea
TL
2035 /* If so directed, use the leased IP address as the router address.
2036 This supposedly makes Win95 machines ARP for all IP addresses,
2037 so if the local router does proxy arp, you win. */
b1dd98c9 2038
5d25508c 2039 if (evaluate_boolean_option_cache
19654922 2040 (&ignorep, packet, lease, packet -> options, state -> options,
12c9957e 2041 &lease -> scope,
951323fe 2042 lookup_option (&server_universe, state -> options,
12c9957e 2043 SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
5d25508c 2044 i = DHO_ROUTERS;
951323fe 2045 oc = lookup_option (&dhcp_universe, state -> options, i);
027f46cb
TL
2046 if (!oc) {
2047 oc = (struct option_cache *)0;
4bd8800e 2048 if (option_cache_allocate (&oc, MDL)) {
027f46cb
TL
2049 if (make_const_data (&oc -> expression,
2050 lease -> ip_addr.iabuf,
2051 lease -> ip_addr.len,
2052 0, 0)) {
2053 oc -> option =
2054 dhcp_universe.options [i];
951323fe
TL
2055 save_option (&dhcp_universe,
2056 state -> options, oc);
027f46cb 2057 }
ba450294 2058 option_cache_dereference (&oc, MDL);
5d25508c 2059 }
b1dd98c9 2060 }
421563ea
TL
2061 }
2062
df598b3e
TL
2063 /* Make an encapsulation for the NWIP suboptions if the client
2064 asked for them. */
2065 i = DHO_NWIP_SUBOPTIONS;
2066 if (!(oc = lookup_option (&dhcp_universe, state -> options, i))) {
2067 oc = (struct option_cache *)0;
4bd8800e 2068 if (option_cache_allocate (&oc, MDL)) {
df598b3e 2069 memset (&d1, 0, sizeof d1);
fb6297b1 2070 d1.data = (const unsigned char *)"nwip";
df598b3e
TL
2071 d1.len = 4;
2072 if (make_encapsulation (&oc -> expression, &d1)) {
2073 oc -> option = dhcp_universe.options [i];
2074 save_option (&dhcp_universe,
2075 state -> options, oc);
2076 }
4bd8800e 2077 option_cache_dereference (&oc, MDL);
df598b3e
TL
2078 }
2079 }
2080
951323fe
TL
2081 /* If we've been given a vendor option space, and there's something
2082 in it, and we weren't given a vendor-encapsulated-options option,
2083 then cons one up. */
2084 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
2085 j = SV_VENDOR_OPTION_SPACE;
2086 if (!lookup_option (&dhcp_universe, state -> options, i) &&
2087 (oc = lookup_option (&server_universe, state -> options, j)) &&
ca1c700e 2088 evaluate_option_cache (&d1, packet, lease,
12c9957e
TL
2089 packet -> options, state -> options,
2090 &lease -> scope, oc, MDL)) {
951323fe 2091 oc = (struct option_cache *)0;
4bd8800e 2092 if (option_cache_allocate (&oc, MDL)) {
951323fe
TL
2093 if (make_encapsulation (&oc -> expression, &d1)) {
2094 oc -> option = dhcp_universe.options [i];
2095 save_option (&dhcp_universe,
2096 state -> options, oc);
2097 }
4bd8800e 2098 option_cache_dereference (&oc, MDL);
951323fe 2099 }
4bd8800e 2100 data_string_forget (&d1, MDL);
951323fe
TL
2101 }
2102
10553ccb
TL
2103 /* If a site option space has been specified, use that for
2104 site option codes. */
2105 i = SV_SITE_OPTION_SPACE;
0af446bc 2106 if ((oc = lookup_option (&server_universe, state -> options, i)) &&
ca1c700e 2107 evaluate_option_cache (&d1, packet, lease,
12c9957e
TL
2108 packet -> options, state -> options,
2109 &lease -> scope, oc, MDL)) {
20916cae
TL
2110 struct universe *u = (struct universe *)0;
2111
2112 if (!universe_hash_lookup (&u, universe_hash,
2113 d1.data, d1.len, MDL)) {
10553ccb
TL
2114 log_error ("unknown option space %s.", d1.data);
2115 return;
2116 }
2117
2118 state -> options -> site_universe = u -> index;
2119 state -> options -> site_code_min = 128; /* XXX */
4bd8800e 2120 data_string_forget (&d1, MDL);
10553ccb
TL
2121 } else {
2122 state -> options -> site_code_min = 0;
2123 state -> options -> site_universe = dhcp_universe.index;
2124 }
2125
eddb16f4 2126 /* If the client has provided a list of options that it wishes
431693d1
TL
2127 returned, use it to prioritize. If there's a parameter
2128 request list in scope, use that in preference. Otherwise
2129 use the default priority list. */
eddb16f4 2130
431693d1 2131 oc = lookup_option (&dhcp_universe, state -> options,
eddb16f4
TL
2132 DHO_DHCP_PARAMETER_REQUEST_LIST);
2133
cdc336ab 2134 if (!oc)
431693d1 2135 oc = lookup_option (&dhcp_universe, packet -> options,
cdc336ab 2136 DHO_DHCP_PARAMETER_REQUEST_LIST);
eddb16f4
TL
2137 if (oc)
2138 evaluate_option_cache (&state -> parameter_request_list,
ca1c700e
TL
2139 packet, lease,
2140 packet -> options, state -> options,
12c9957e 2141 &lease -> scope, oc, MDL);
eddb16f4 2142
11b37280
TL
2143#ifdef DEBUG_PACKET
2144 dump_packet (packet);
2145 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
2146#endif
2147
9cc3ad7f 2148 lease -> state = state;
4b7df707 2149
8ae2d595 2150 log_info ("%s", msg);
c4924529 2151
ca1c700e 2152 /* Hang the packet off the lease state. */
4bd8800e 2153 packet_reference (&lease -> state -> packet, packet, MDL);
ca1c700e 2154
4b7df707
TL
2155 /* If this is a DHCPOFFER, ping the lease address before actually
2156 sending the offer. */
027f46cb
TL
2157 if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
2158 cur_time - lease -> timestamp > 60) {
2159 lease -> timestamp = cur_time;
4b7df707 2160 icmp_echorequest (&lease -> ip_addr);
20916cae
TL
2161 add_timeout (cur_time + 1, lease_ping_timeout, lease,
2162 (tvref_t)lease_reference,
2163 (tvunref_t)lease_dereference);
4b7df707
TL
2164 ++outstanding_pings;
2165 } else {
027f46cb 2166 lease -> timestamp = cur_time;
4bd8800e 2167 static_lease_dereference (lease, MDL);
4b7df707
TL
2168 dhcp_reply (lease);
2169 }
11b37280
TL
2170}
2171
2172void dhcp_reply (lease)
2173 struct lease *lease;
2174{
2175 int bufs = 0;
b1b7b521 2176 unsigned packet_length;
11b37280
TL
2177 struct dhcp_packet raw;
2178 struct sockaddr_in to;
2179 struct in_addr from;
2180 struct hardware hto;
2181 int result;
2182 int i;
9cc3ad7f 2183 struct lease_state *state = lease -> state;
a52d8045 2184 int nulltp, bootpp;
3c893bb6
TL
2185 struct agent_options *a, *na;
2186 struct option_tag *ot, *not;
b1dd98c9 2187 struct data_string d1;
5d25508c 2188 struct option_cache *oc;
d9eefc5d 2189 char *s;
9cc3ad7f
TL
2190
2191 if (!state)
8ae2d595 2192 log_fatal ("dhcp_reply was supplied lease with no state!");
11b37280 2193
9cc3ad7f 2194 /* Compose a response for the client... */
11b37280 2195 memset (&raw, 0, sizeof raw);
5d25508c 2196 memset (&d1, 0, sizeof d1);
11b37280
TL
2197
2198 /* Copy in the filename if given; otherwise, flag the filename
2199 buffer as available for options. */
b1dd98c9
TL
2200 if (state -> filename.len && state -> filename.data) {
2201 memcpy (raw.file,
2202 state -> filename.data,
2203 state -> filename.len > sizeof raw.file
2204 ? sizeof raw.file : state -> filename.len);
2205 if (sizeof raw.file > state -> filename.len)
2206 memset (&raw.file [state -> filename.len], 0,
2207 (sizeof raw.file) - state -> filename.len);
2208 } else
11b37280
TL
2209 bufs |= 1;
2210
2211 /* Copy in the server name if given; otherwise, flag the
2212 server_name buffer as available for options. */
b1dd98c9
TL
2213 if (state -> server_name.len && state -> server_name.data) {
2214 memcpy (raw.sname,
2215 state -> server_name.data,
2216 state -> server_name.len > sizeof raw.sname
2217 ? sizeof raw.sname : state -> server_name.len);
2218 if (sizeof raw.sname > state -> server_name.len)
2219 memset (&raw.sname [state -> server_name.len], 0,
2220 (sizeof raw.sname) - state -> server_name.len);
2221 } else
11b37280
TL
2222 bufs |= 2; /* XXX */
2223
2cbc0e48
TL
2224 memcpy (raw.chaddr,
2225 &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
2226 raw.hlen = lease -> hardware_addr.hlen - 1;
2227 raw.htype = lease -> hardware_addr.hbuf [0];
11b37280 2228
c34fcd38
TL
2229 /* See if this is a Microsoft client that NUL-terminates its
2230 strings and expects us to do likewise... */
11b37280 2231 if (lease -> flags & MS_NULL_TERMINATION)
a52d8045 2232 nulltp = 1;
c34fcd38 2233 else
a52d8045
TL
2234 nulltp = 0;
2235
2236 /* See if this is a bootp client... */
2237 if (state -> offer)
2238 bootpp = 0;
2239 else
2240 bootpp = 1;
2241
2242 /* Insert such options as will fit into the buffer. */
ca1c700e 2243 packet_length = cons_options (state -> packet, &raw, lease,
3c893bb6 2244 state -> max_message_size,
ca1c700e 2245 state -> packet -> options,
12c9957e 2246 state -> options, &global_scope,
eddb16f4
TL
2247 bufs, nulltp, bootpp,
2248 &state -> parameter_request_list);
11b37280 2249
9cc3ad7f 2250 memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
685963dc 2251 memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
10553ccb 2252 raw.siaddr = state -> siaddr;
9cc3ad7f 2253 raw.giaddr = state -> giaddr;
685963dc 2254
9cc3ad7f
TL
2255 raw.xid = state -> xid;
2256 raw.secs = state -> secs;
2257 raw.flags = state -> bootp_flags;
2258 raw.hops = state -> hops;
685963dc
TL
2259 raw.op = BOOTREPLY;
2260
d9eefc5d
TL
2261 if (lease -> client_hostname &&
2262 db_printable (lease -> client_hostname))
2263 s = lease -> client_hostname;
2264 else
2265 s = (char *)0;
2266
7a049f2c 2267 /* Say what we're doing... */
d9eefc5d 2268 log_info ("%s on %s to %s %s%s%svia %s",
86bbcc1c
TL
2269 (state -> offer
2270 ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
2271 : "BOOTREPLY"),
2272 piaddr (lease -> ip_addr),
2cbc0e48
TL
2273 (lease -> hardware_addr.hlen
2274 ? print_hw_addr (lease -> hardware_addr.hbuf [0],
2275 lease -> hardware_addr.hlen - 1,
2276 &lease -> hardware_addr.hbuf [1])
d9eefc5d
TL
2277 : print_hex_1 (lease -> uid_len, lease -> uid,
2278 lease -> uid_len)),
fdd46b53
TL
2279 s ? "(" : "", s ? s : "", s ? ") " : "",
2280 (state -> giaddr.s_addr
2281 ? inet_ntoa (state -> giaddr)
2282 : state -> ip -> name));
7a049f2c
TL
2283
2284 /* Set up the hardware address... */
11b37280 2285 hto.hlen = lease -> hardware_addr.hlen;
2cbc0e48 2286 memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
7a049f2c
TL
2287
2288 to.sin_family = AF_INET;
2289#ifdef HAVE_SA_LEN
2290 to.sin_len = sizeof to;
2291#endif
2292 memset (to.sin_zero, 0, sizeof to.sin_zero);
2293
2294#ifdef DEBUG_PACKET
11b37280 2295 dump_raw ((unsigned char *)&raw, packet_length);
7a049f2c
TL
2296#endif
2297
11b37280
TL
2298 /* Make sure outgoing packets are at least as big
2299 as a BOOTP packet. */
2300 if (packet_length < BOOTP_MIN_LEN)
2301 packet_length = BOOTP_MIN_LEN;
2302
ed8bcd8f 2303 /* If this was gatewayed, send it back to the gateway... */
b88e8e15 2304 if (raw.giaddr.s_addr) {
ed8bcd8f 2305 to.sin_addr = raw.giaddr;
1b871100
TL
2306 if (raw.giaddr.s_addr != INADDR_LOOPBACK)
2307 to.sin_port = local_port;
2308 else
2309 to.sin_port = remote_port; /* For debugging. */
8ec97099 2310
027f46cb
TL
2311 if (fallback_interface) {
2312 result = send_packet (fallback_interface,
2313 (struct packet *)0,
2314 &raw, packet_length,
566ecd40
TL
2315 raw.siaddr, &to,
2316 (struct hardware *)0);
9cc3ad7f 2317
4bd8800e 2318 free_lease_state (state, MDL);
027f46cb
TL
2319 lease -> state = (struct lease_state *)0;
2320 return;
2321 }
b88e8e15 2322
566ecd40 2323 /* If the client is RENEWING, unicast to the client using the
cdc336ab
TL
2324 regular IP stack. Some clients, particularly those that
2325 follow RFC1541, are buggy, and send both ciaddr and server
2326 identifier. We deal with this situation by assuming that
2327 if we got both dhcp-server-identifier and ciaddr, and
2328 giaddr was not set, then the client is on the local
2329 network, and we can therefore unicast or broadcast to it
2330 successfully. A client in REQUESTING state on another
2331 network that's making this mistake will have set giaddr,
2332 and will therefore get a relayed response from the above
2333 code. */
2334 } else if (raw.ciaddr.s_addr &&
0af446bc
TL
2335 !((state -> got_server_identifier ||
2336 (raw.flags & htons (BOOTP_BROADCAST))) &&
2337 /* XXX This won't work if giaddr isn't zero, but it is: */
cdc336ab
TL
2338 (state -> shared_network ==
2339 lease -> subnet -> shared_network)) &&
2340 state -> offer == DHCPACK) {
531fa185 2341 to.sin_addr = raw.ciaddr;
566ecd40 2342 to.sin_port = remote_port;
b88e8e15 2343
027f46cb
TL
2344 if (fallback_interface) {
2345 result = send_packet (fallback_interface,
2346 (struct packet *)0,
2347 &raw, packet_length,
566ecd40
TL
2348 raw.siaddr, &to,
2349 (struct hardware *)0);
4bd8800e 2350 free_lease_state (state, MDL);
027f46cb
TL
2351 lease -> state = (struct lease_state *)0;
2352 return;
2353 }
e2cb6d53 2354
566ecd40
TL
2355 /* If it comes from a client that already knows its address
2356 and is not requesting a broadcast response, and we can
2357 unicast to a client without using the ARP protocol, sent it
2358 directly to that client. */
2359 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
531fa185
TL
2360 can_unicast_without_arp (state -> ip)) {
2361 to.sin_addr = raw.yiaddr;
566ecd40
TL
2362 to.sin_port = remote_port;
2363
ed8bcd8f 2364 /* Otherwise, broadcast it on the local network. */
b88e8e15 2365 } else {
71df44f5 2366 to.sin_addr = limited_broadcast;
566ecd40 2367 to.sin_port = remote_port;
b88e8e15 2368 }
ed8bcd8f 2369
5d25508c 2370 memcpy (&from, state -> from.iabuf, sizeof from);
fde927d2 2371
9cc3ad7f 2372 result = send_packet (state -> ip,
11b37280 2373 (struct packet *)0, &raw, packet_length,
5d25508c 2374 from, &to, &hto);
9cc3ad7f 2375
10553ccb
TL
2376 /* Free all of the entries in the option_state structure
2377 now that we're done with them. */
2378
4bd8800e 2379 free_lease_state (state, MDL);
9cc3ad7f 2380 lease -> state = (struct lease_state *)0;
d7837182 2381}
ed8bcd8f 2382
20916cae
TL
2383int find_lease (struct lease **lp,
2384 struct packet *packet, struct shared_network *share, int *ours,
2385 const char *file, int line)
ed8bcd8f 2386{
20916cae
TL
2387 struct lease *uid_lease = (struct lease *)0;
2388 struct lease *ip_lease = (struct lease *)0;
2389 struct lease *hw_lease = (struct lease *)0;
7a049f2c 2390 struct lease *lease = (struct lease *)0;
ed8bcd8f 2391 struct iaddr cip;
20916cae
TL
2392 struct host_decl *hp = (struct host_decl *)0;
2393 struct host_decl *host = (struct host_decl *)0;
2394 struct lease *fixed_lease = (struct lease *)0;
2395 struct lease *next;
5d25508c
TL
2396 struct option_cache *oc;
2397 struct data_string d1;
2398 int have_client_identifier = 0;
2399 struct data_string client_identifier;
2400 int status;
4d0aaa17 2401 struct hardware h;
ed8bcd8f 2402
74f45f96 2403 /* Look up the requested address. */
951323fe 2404 oc = lookup_option (&dhcp_universe, packet -> options,
74f45f96
TL
2405 DHO_DHCP_REQUESTED_ADDRESS);
2406 memset (&d1, 0, sizeof d1);
2407 if (oc &&
ca1c700e
TL
2408 evaluate_option_cache (&d1, packet, (struct lease *)0,
2409 packet -> options, (struct option_state *)0,
12c9957e 2410 &global_scope, oc, MDL)) {
cdc336ab 2411 packet -> got_requested_address = 1;
74f45f96
TL
2412 cip.len = 4;
2413 memcpy (cip.iabuf, d1.data, cip.len);
4bd8800e 2414 data_string_forget (&d1, MDL);
74f45f96
TL
2415 } else if (packet -> raw -> ciaddr.s_addr) {
2416 cip.len = 4;
2417 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
2418 } else
2419 cip.len = 0;
2420
7a049f2c
TL
2421 /* Try to find a host or lease that's been assigned to the
2422 specified unique client identifier. */
951323fe 2423 oc = lookup_option (&dhcp_universe, packet -> options,
5d25508c
TL
2424 DHO_DHCP_CLIENT_IDENTIFIER);
2425 memset (&client_identifier, 0, sizeof client_identifier);
2426 if (oc &&
2427 evaluate_option_cache (&client_identifier,
ca1c700e
TL
2428 packet, (struct lease *)0,
2429 packet -> options, (struct option_state *)0,
12c9957e 2430 &global_scope, oc, MDL)) {
5d25508c
TL
2431 /* Remember this for later. */
2432 have_client_identifier = 1;
2433
7a049f2c
TL
2434 /* First, try to find a fixed host entry for the specified
2435 client identifier... */
20916cae
TL
2436 if (find_hosts_by_uid (&hp, client_identifier.data,
2437 client_identifier.len, MDL)) {
f63b4929
TL
2438 /* Remember if we know of this client. */
2439 packet -> known = 1;
20916cae
TL
2440 mockup_lease (&fixed_lease, packet, share, hp);
2441 }
5d25508c 2442
5d25508c 2443#if defined (DEBUG_FIND_LEASE)
74f45f96 2444 if (fixed_lease) {
8ae2d595 2445 log_info ("Found host for client identifier: %s.",
5d25508c 2446 piaddr (fixed_lease -> ip_addr));
74f45f96 2447 }
5d25508c 2448#endif
20916cae
TL
2449 if (!fixed_lease) /* Save the host if we found one. */
2450 host_reference (&host, hp, MDL);
2451 if (hp)
2452 host_dereference (&hp, MDL);
5d25508c 2453
20916cae
TL
2454 find_lease_by_uid (&uid_lease, client_identifier.data,
2455 client_identifier.len, MDL);
7a049f2c
TL
2456 }
2457
2458 /* If we didn't find a fixed lease using the uid, try doing
2459 it with the hardware address... */
5d25508c 2460 if (!fixed_lease && !host) {
20916cae
TL
2461 if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
2462 packet -> raw -> chaddr,
2463 packet -> raw -> hlen, MDL)) {
f63b4929
TL
2464 /* Remember if we know of this client. */
2465 packet -> known = 1;
20916cae
TL
2466 if (host)
2467 host_dereference (&host, MDL);
2468 host_reference (&host, hp, MDL);
2469 host_dereference (&hp, MDL);
2470 mockup_lease (&fixed_lease, packet, share, host);
5d25508c
TL
2471#if defined (DEBUG_FIND_LEASE)
2472 if (fixed_lease) {
74f45f96 2473 log_info ("Found host for link address: %s.",
5d25508c
TL
2474 piaddr (fixed_lease -> ip_addr));
2475 }
2476#endif
7a049f2c
TL
2477 }
2478 }
ed8bcd8f 2479
74f45f96
TL
2480 /* If fixed_lease is present but does not match the requested
2481 IP address, and this is a DHCPREQUEST, then we can't return
2482 any other lease, so we might as well return now. */
2483 if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
2484 (fixed_lease -> ip_addr.len != cip.len ||
2485 memcmp (fixed_lease -> ip_addr.iabuf,
2486 cip.iabuf, cip.len))) {
2487 if (ours)
2488 *ours = 1;
2489 strcpy (dhcp_message, "requested address is incorrect");
2490#if defined (DEBUG_FIND_LEASE)
2491 log_info ("Client's fixed-address %s doesn't match %s%s",
2492 piaddr (fixed_lease -> ip_addr), "request ",
2493 print_dotted_quads (cip.len, cip.iabuf));
2494#endif
2495 goto out;
2496 }
2497
2498 /* If we found leases matching the client identifier, loop through
2499 the n_uid pointer looking for one that's actually valid. We
2500 can't do this until we get here because we depend on
2501 packet -> known, which may be set by either the uid host
2502 lookup or the haddr host lookup. */
20916cae 2503 while (uid_lease) {
74f45f96
TL
2504#if defined (DEBUG_FIND_LEASE)
2505 log_info ("trying next lease matching client id: %s",
2506 piaddr (uid_lease -> ip_addr));
2507#endif
2508 if (uid_lease -> subnet -> shared_network != share) {
2509#if defined (DEBUG_FIND_LEASE)
2510 log_info ("wrong network segment: %s",
2511 piaddr (uid_lease -> ip_addr));
2512#endif
2513 next = uid_lease -> n_uid;
20916cae
TL
2514 lease_dereference (&uid_lease, MDL);
2515 lease_reference (&uid_lease, next, MDL);
74f45f96
TL
2516 continue;
2517 }
2518 if ((uid_lease -> pool -> prohibit_list &&
951323fe 2519 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
74f45f96
TL
2520 (uid_lease -> pool -> permit_list &&
2521 !permitted (packet, uid_lease -> pool -> permit_list))) {
2522#if defined (DEBUG_FIND_LEASE)
2523 log_info ("not permitted: %s",
2524 piaddr (uid_lease -> ip_addr));
2525#endif
2526 next = uid_lease -> n_uid;
2527 if (!packet -> raw -> ciaddr.s_addr)
43f23dcc 2528 release_lease (uid_lease, packet);
20916cae
TL
2529 lease_dereference (&uid_lease, MDL);
2530 lease_reference (&uid_lease, next, MDL);
74f45f96
TL
2531 continue;
2532 }
2533 break;
2534 }
2535#if defined (DEBUG_FIND_LEASE)
2536 if (uid_lease)
2537 log_info ("Found lease for client id: %s.",
2538 piaddr (uid_lease -> ip_addr));
2539#endif
2540
2541 /* Find a lease whose hardware address matches, whose client
2542 identifier matches, that's permitted, and that's on the
2543 correct subnet. */
4d0aaa17
TL
2544 h.hlen = packet -> raw -> hlen + 1;
2545 h.hbuf [0] = packet -> raw -> htype;
2546 memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
20916cae
TL
2547 find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
2548 while (hw_lease) {
74f45f96
TL
2549#if defined (DEBUG_FIND_LEASE)
2550 log_info ("trying next lease matching hw addr: %s",
2551 piaddr (hw_lease -> ip_addr));
2552#endif
2553 if (hw_lease -> ends >= cur_time &&
2554 hw_lease -> uid &&
2555 (!have_client_identifier ||
2556 hw_lease -> uid_len != client_identifier.len ||
2557 memcmp (hw_lease -> uid, client_identifier.data,
2558 hw_lease -> uid_len))) {
2559#if defined (DEBUG_FIND_LEASE)
2560 log_info ("wrong client identifier: %s",
2561 piaddr (hw_lease -> ip_addr));
2562#endif
2563 next = hw_lease -> n_hw;
20916cae
TL
2564 lease_dereference (&hw_lease, MDL);
2565 lease_reference (&hw_lease, next, MDL);
74f45f96
TL
2566 continue;
2567 }
2568 if (hw_lease -> subnet -> shared_network != share) {
2569#if defined (DEBUG_FIND_LEASE)
2570 log_info ("wrong network segment: %s",
2571 piaddr (hw_lease -> ip_addr));
2572#endif
2573 next = hw_lease -> n_hw;
20916cae
TL
2574 lease_dereference (&hw_lease, MDL);
2575 lease_reference (&hw_lease, next, MDL);
74f45f96 2576 continue;
355bf452 2577 }
74f45f96
TL
2578 if ((hw_lease -> pool -> prohibit_list &&
2579 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
2580 (hw_lease -> pool -> permit_list &&
2581 !permitted (packet, hw_lease -> pool -> permit_list))) {
2582#if defined (DEBUG_FIND_LEASE)
2583 log_info ("not permitted: %s",
2584 piaddr (hw_lease -> ip_addr));
2585#endif
2586 next = hw_lease -> n_hw;
2587 if (!packet -> raw -> ciaddr.s_addr)
43f23dcc 2588 release_lease (hw_lease, packet);
20916cae
TL
2589 lease_dereference (&hw_lease, MDL);
2590 lease_reference (&hw_lease, next, MDL);
74f45f96
TL
2591 continue;
2592 }
2593 break;
355bf452 2594 }
5d25508c
TL
2595#if defined (DEBUG_FIND_LEASE)
2596 if (hw_lease)
8ae2d595 2597 log_info ("Found lease for hardware address: %s.",
5d25508c
TL
2598 piaddr (hw_lease -> ip_addr));
2599#endif
ed8bcd8f
TL
2600
2601 /* Try to find a lease that's been allocated to the client's
2602 IP address. */
74f45f96 2603 if (cip.len)
20916cae 2604 find_lease_by_ip_addr (&ip_lease, cip, MDL);
5d25508c
TL
2605
2606#if defined (DEBUG_FIND_LEASE)
2607 if (ip_lease)
8ae2d595 2608 log_info ("Found lease for requested address: %s.",
5d25508c
TL
2609 piaddr (ip_lease -> ip_addr));
2610#endif
ed8bcd8f 2611
fa97acc1
TL
2612 /* If ip_lease is valid at this point, set ours to one, so that
2613 even if we choose a different lease, we know that the address
2614 the client was requesting was ours, and thus we can NAK it. */
be6b4b2a 2615 if (ip_lease && ours)
fa97acc1
TL
2616 *ours = 1;
2617
4fbcd991 2618 /* If the requested IP address isn't on the network the packet
c54885bd
TL
2619 came from, don't use it. Allow abandoned leases to be matched
2620 here - if the client is requesting it, there's a decent chance
2621 that it's because the lease database got trashed and a client
2622 that thought it had this lease answered an ARP or PING, causing the
2623 lease to be abandoned. If so, this request probably came from
2624 that client. */
027f46cb 2625 if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
74f45f96
TL
2626 if (ours)
2627 *ours = 1;
2628#if defined (DEBUG_FIND_LEASE)
8ae2d595 2629 log_info ("...but it was on the wrong shared network.");
74f45f96
TL
2630#endif
2631 strcpy (dhcp_message, "requested address on bad subnet");
20916cae 2632 lease_dereference (&ip_lease, MDL);
5d25508c 2633 }
4fbcd991 2634
eeea1395
TL
2635 /* Toss ip_lease if it hasn't yet expired and doesn't belong to the
2636 client. */
f8cd781e
TL
2637 if (ip_lease &&
2638 ip_lease -> ends >= cur_time &&
eeea1395
TL
2639 ((ip_lease -> uid &&
2640 (!have_client_identifier ||
2641 ip_lease -> uid_len != client_identifier.len ||
2642 memcmp (ip_lease -> uid, client_identifier.data,
2643 ip_lease -> uid_len))) ||
2644 (!ip_lease -> uid &&
2cbc0e48
TL
2645 (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
2646 ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
4d0aaa17 2647 memcmp (&ip_lease -> hardware_addr.hbuf [1],
eeea1395 2648 packet -> raw -> chaddr,
2cbc0e48 2649 (unsigned)(ip_lease -> hardware_addr.hlen - 1)))))) {
5d25508c
TL
2650#if defined (DEBUG_FIND_LEASE)
2651 if (ip_lease)
8ae2d595 2652 log_info ("rejecting lease for requested address.");
5d25508c 2653#endif
20916cae 2654 lease_dereference (&ip_lease, MDL);
5d25508c
TL
2655 }
2656
2657 /* If for some reason the client has more than one lease
2658 on the subnet that matches its uid, pick the one that
2659 it asked for and (if we can) free the other. */
74f45f96
TL
2660 if (ip_lease &&
2661 ip_lease -> ends >= cur_time &&
2662 ip_lease -> uid && ip_lease != uid_lease) {
2663 if (have_client_identifier &&
5d25508c
TL
2664 (ip_lease -> uid_len == client_identifier.len) &&
2665 !memcmp (client_identifier.data,
599c23c1 2666 ip_lease -> uid, ip_lease -> uid_len)) {
eeea1395
TL
2667 if (uid_lease) {
2668 if (uid_lease -> ends > cur_time) {
74f45f96 2669 log_error ("client %s has duplicate%s on %s",
74f45f96
TL
2670 (print_hw_addr
2671 (packet -> raw -> htype,
2672 packet -> raw -> hlen,
2673 packet -> raw -> chaddr)),
12c9957e
TL
2674 " leases",
2675 (ip_lease -> subnet ->
2676 shared_network -> name));
48984237 2677
eeea1395
TL
2678 /* If the client is REQUESTing the lease,
2679 it shouldn't still be using the old
2680 one, so we can free it for allocation. */
2681 if (uid_lease &&
2682 !packet -> raw -> ciaddr.s_addr &&
2683 (share ==
a1e9fabd
TL
2684 uid_lease -> subnet -> shared_network) &&
2685 packet -> packet_type == DHCPREQUEST)
eeea1395
TL
2686 dissociate_lease (uid_lease);
2687 }
20916cae
TL
2688 lease_dereference (&uid_lease, MDL);
2689 lease_reference (&uid_lease, ip_lease, MDL);
eeea1395 2690 }
599c23c1 2691 }
f8cd781e 2692
74f45f96
TL
2693 /* If we get to here and fixed_lease is not null, that means
2694 that there are both a dynamic lease and a fixed-address
2695 declaration for the same IP address. */
2696 if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
20916cae 2697 lease_dereference (&fixed_lease, MDL);
74f45f96 2698 db_conflict:
c5b0f529
TL
2699 log_error ("Dynamic and static leases present for %s.",
2700 piaddr (cip));
2701 log_error ("Remove host declaration %s or remove %s",
2702 (fixed_lease && fixed_lease -> host
2703 ? (fixed_lease -> host -> name
2704 ? fixed_lease -> host -> name
2705 : piaddr (cip))
2706 : piaddr (cip)),
2707 piaddr (cip));
2708 log_error ("from the dynamic address pool for %s",
2709 ip_lease -> subnet -> shared_network -> name
2710 );
74f45f96 2711 if (fixed_lease)
20916cae 2712 lease_dereference (&ip_lease, MDL);
74f45f96
TL
2713 strcpy (dhcp_message,
2714 "database conflict - call for help!");
2715 }
5d25508c 2716 }
f8cd781e 2717
74f45f96
TL
2718 /* If we get to here with both fixed_lease and ip_lease not
2719 null, then we have a configuration file bug. */
2720 if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
2721 goto db_conflict;
2722
2723 /* Make sure the client is permitted to use the requested lease. */
2724 if (ip_lease &&
2725 ((ip_lease -> pool -> prohibit_list &&
2726 permitted (packet, ip_lease -> pool -> prohibit_list)) ||
2727 (ip_lease -> pool -> permit_list &&
2728 !permitted (packet, ip_lease -> pool -> permit_list)))) {
2729 if (!packet -> raw -> ciaddr.s_addr)
43f23dcc 2730 release_lease (ip_lease, packet);
20916cae 2731 lease_dereference (&ip_lease, MDL);
5d25508c 2732 }
74f45f96
TL
2733
2734 /* Toss extra pointers to the same lease... */
20916cae 2735 if (hw_lease && hw_lease == uid_lease) {
5d25508c 2736#if defined (DEBUG_FIND_LEASE)
8ae2d595 2737 log_info ("hardware lease and uid lease are identical.");
5d25508c 2738#endif
20916cae 2739 lease_dereference (&hw_lease, MDL);
5d25508c 2740 }
20916cae
TL
2741 if (ip_lease && ip_lease == hw_lease) {
2742 lease_dereference (&hw_lease, MDL);
74f45f96
TL
2743#if defined (DEBUG_FIND_LEASE)
2744 log_info ("hardware lease and ip lease are identical.");
2745#endif
2746 }
20916cae
TL
2747 if (ip_lease && ip_lease == uid_lease) {
2748 lease_dereference (&uid_lease, MDL);
5d25508c 2749#if defined (DEBUG_FIND_LEASE)
8ae2d595 2750 log_info ("uid lease and ip lease are identical.");
5d25508c
TL
2751#endif
2752 }
ed8bcd8f 2753
b88e8e15
TL
2754 /* If we've already eliminated the lease, it wasn't there to
2755 begin with. If we have come up with a matching lease,
2756 set the message to bad network in case we have to throw it out. */
74f45f96 2757 if (!ip_lease) {
b88e8e15 2758 strcpy (dhcp_message, "requested address not available");
b88e8e15
TL
2759 }
2760
74f45f96
TL
2761 /* If this is a DHCPREQUEST, make sure the lease we're going to return
2762 matches the requested IP address. If it doesn't, don't return a
2763 lease at all. */
2764 if (packet -> packet_type == DHCPREQUEST &&
2765 !ip_lease && !fixed_lease) {
5d25508c 2766#if defined (DEBUG_FIND_LEASE)
74f45f96 2767 log_info ("no applicable lease found for DHCPREQUEST.");
5d25508c 2768#endif
74f45f96 2769 goto out;
ed8bcd8f
TL
2770 }
2771
7a049f2c 2772 /* At this point, if fixed_lease is nonzero, we can assign it to
ed8bcd8f 2773 this client. */
4fbcd991 2774 if (fixed_lease) {
20916cae
TL
2775 lease_reference (&lease, fixed_lease, MDL);
2776 lease_dereference (&fixed_lease, MDL);
5d25508c 2777#if defined (DEBUG_FIND_LEASE)
8ae2d595 2778 log_info ("choosing fixed address.");
5d25508c 2779#endif
4fbcd991 2780 }
7a049f2c
TL
2781
2782 /* If we got a lease that matched the ip address and don't have
2783 a better offer, use that; otherwise, release it. */
2784 if (ip_lease) {
2785 if (lease) {
74f45f96 2786 if (!packet -> raw -> ciaddr.s_addr)
43f23dcc 2787 release_lease (ip_lease, packet);
5d25508c 2788#if defined (DEBUG_FIND_LEASE)
8ae2d595 2789 log_info ("not choosing requested address (!).");
5d25508c 2790#endif
7a049f2c 2791 } else {
5d25508c 2792#if defined (DEBUG_FIND_LEASE)
8ae2d595 2793 log_info ("choosing lease on requested address.");
5d25508c 2794#endif
20916cae
TL
2795 lease_reference (&lease, ip_lease, MDL);
2796 if (lease -> host)
2797 host_dereference (&lease -> host, MDL);
7a049f2c 2798 }
20916cae 2799 lease_dereference (&ip_lease, MDL);
7a049f2c 2800 }
ed8bcd8f
TL
2801
2802 /* If we got a lease that matched the client identifier, we may want
2803 to use it, but if we already have a lease we like, we must free
2804 the lease that matched the client identifier. */
2805 if (uid_lease) {
2806 if (lease) {
a1e9fabd
TL
2807 if (!packet -> raw -> ciaddr.s_addr &&
2808 packet -> packet_type == DHCPREQUEST)
421563ea 2809 dissociate_lease (uid_lease);
5d25508c 2810#if defined (DEBUG_FIND_LEASE)
8ae2d595 2811 log_info ("not choosing uid lease.");
5d25508c 2812#endif
20916cae 2813 lease_dereference (&uid_lease, MDL);
7a049f2c 2814 } else {
20916cae
TL
2815 lease_reference (&lease, uid_lease, MDL);
2816 if (lease -> host)
2817 host_dereference (&lease -> host, MDL);
5d25508c 2818#if defined (DEBUG_FIND_LEASE)
8ae2d595 2819 log_info ("choosing uid lease.");
5d25508c 2820#endif
7a049f2c 2821 }
20916cae 2822 lease_dereference (&uid_lease, MDL);
ed8bcd8f
TL
2823 }
2824
2825 /* The lease that matched the hardware address is treated likewise. */
2826 if (hw_lease) {
2827 if (lease) {
a1e9fabd
TL
2828 if (!packet -> raw -> ciaddr.s_addr &&
2829 packet -> packet_type == DHCPREQUEST)
421563ea 2830 dissociate_lease (hw_lease);
20916cae 2831 lease_dereference (&hw_lease, MDL);
5d25508c 2832#if defined (DEBUG_FIND_LEASE)
8ae2d595 2833 log_info ("not choosing hardware lease.");
5d25508c 2834#endif
7a049f2c 2835 } else {
20916cae
TL
2836 lease_reference (&lease, hw_lease, MDL);
2837 if (lease -> host)
2838 host_dereference (&lease -> host, MDL);
5d25508c 2839#if defined (DEBUG_FIND_LEASE)
8ae2d595 2840 log_info ("choosing hardware lease.");
5d25508c 2841#endif
7a049f2c 2842 }
20916cae 2843 lease_dereference (&hw_lease, MDL);
7a049f2c
TL
2844 }
2845
2846 /* If we found a host_decl but no matching address, try to
2847 find a host_decl that has no address, and if there is one,
2848 hang it off the lease so that we can use the supplied
2849 options. */
2850 if (lease && host && !lease -> host) {
2851 for (; host; host = host -> n_ipaddr) {
2852 if (!host -> fixed_addr) {
20916cae 2853 host_reference (&lease -> host, host, MDL);
7a049f2c
TL
2854 break;
2855 }
2856 }
ed8bcd8f
TL
2857 }
2858
027f46cb
TL
2859 /* If we find an abandoned lease, but it's the one the client
2860 requested, we assume that previous bugginess on the part
2861 of the client, or a server database loss, caused the lease to
2862 be abandoned, so we reclaim it and let the client have it. */
0af446bc 2863 if (lease && (lease -> flags & ABANDONED_LEASE) && lease == ip_lease &&
027f46cb 2864 packet -> packet_type == DHCPREQUEST) {
8ae2d595 2865 log_error ("Reclaiming REQUESTed abandoned IP address %s.",
c54885bd
TL
2866 piaddr (lease -> ip_addr));
2867 lease -> flags &= ~ABANDONED_LEASE;
0af446bc 2868 } else if (lease && (lease -> flags & ABANDONED_LEASE)) {
027f46cb
TL
2869 /* Otherwise, if it's not the one the client requested, we do not
2870 return it - instead, we claim it's ours, causing a DHCPNAK to be
2871 sent if this lookup is for a DHCPREQUEST, and force the client
2872 to go back through the allocation process. */
2873 if (ours)
2874 *ours = 1;
20916cae 2875 lease_dereference (&lease, MDL);
c54885bd
TL
2876 }
2877
74f45f96
TL
2878 out:
2879 if (have_client_identifier)
4bd8800e 2880 data_string_forget (&client_identifier, MDL);
74f45f96 2881
20916cae
TL
2882 if (fixed_lease)
2883 lease_dereference (&fixed_lease, MDL);
2884 if (hw_lease)
2885 lease_dereference (&hw_lease, MDL);
2886 if (uid_lease)
2887 lease_dereference (&uid_lease, MDL);
2888 if (ip_lease)
2889 lease_dereference (&ip_lease, MDL);
2890 if (host)
2891 host_dereference (&host, MDL);
2892
2893 if (lease) {
74f45f96 2894#if defined (DEBUG_FIND_LEASE)
74f45f96
TL
2895 log_info ("Returning lease: %s.",
2896 piaddr (lease -> ip_addr));
74f45f96 2897#endif
20916cae
TL
2898 lease_reference (lp, lease, file, line);
2899 lease_dereference (&lease, MDL);
2900 return 1;
2901 }
2902#if defined (DEBUG_FIND_LEASE)
2903 log_info ("Not returning a lease.");
2904#endif
2905 return 0;
ed8bcd8f 2906}
7a049f2c
TL
2907
2908/* Search the provided host_decl structure list for an address that's on
2909 the specified shared network. If one is found, mock up and return a
2910 lease structure for it; otherwise return the null pointer. */
2911
20916cae
TL
2912int mockup_lease (struct lease **lp, struct packet *packet,
2913 struct shared_network *share, struct host_decl *hp)
7a049f2c 2914{
20916cae 2915 struct lease *lease = (struct lease *)0;
fb6297b1 2916 const unsigned char **s;
20916cae 2917 isc_result_t status;
7a049f2c 2918
20916cae
TL
2919 status = lease_allocate (&lease, MDL);
2920 if (status != ISC_R_SUCCESS)
2921 return 0;
2922 if (!find_host_for_network (&lease -> subnet,
2923 &hp, &lease -> ip_addr, share)) {
2924 lease_dereference (&lease, MDL);
2925 return 0;
2926 }
2927 host_reference (&lease -> host, hp, MDL);
2928 if (hp -> client_identifier.len > sizeof lease -> uid_buf)
2929 lease -> uid = dmalloc (hp -> client_identifier.len, MDL);
fb6297b1 2930 else
20916cae
TL
2931 lease -> uid = lease -> uid_buf;
2932 if (!lease -> uid) {
2933 lease_dereference (&lease, MDL);
2934 return 0;
2935 }
2936 memcpy (lease -> uid, hp -> client_identifier.data,
fb6297b1 2937 hp -> client_identifier.len);
20916cae
TL
2938 lease -> uid_len = hp -> client_identifier.len;
2939 lease -> hardware_addr = hp -> interface;
2940 lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
2941 lease -> flags = STATIC_LEASE;
2942 lease_reference (lp, lease, MDL);
2943 lease_dereference (&lease, MDL);
2944 return 1;
7a049f2c 2945}
f63b4929 2946
6c8a5472
TL
2947/* Dereference all dynamically-allocated information that may be dangling
2948 off of a static lease. Otherwise, once ack_lease returns, the information
2949 dangling from the lease will be lost, so reference counts will be screwed
2950 up and memory leaks will occur. */
2951
4bd8800e 2952void static_lease_dereference (lease, file, line)
6c8a5472 2953 struct lease *lease;
4bd8800e
TL
2954 const char *file;
2955 int line;
6c8a5472
TL
2956{
2957 if (!(lease -> flags & STATIC_LEASE))
2958 return;
2959 if (lease -> on_release)
4bd8800e
TL
2960 executable_statement_dereference (&lease -> on_release,
2961 file, line);
6c8a5472 2962 if (lease -> on_expiry)
4bd8800e
TL
2963 executable_statement_dereference (&lease -> on_expiry,
2964 file, line);
6c8a5472 2965 if (lease -> on_commit)
4bd8800e
TL
2966 executable_statement_dereference (&lease -> on_commit,
2967 file, line);
12c9957e 2968 if (&lease -> scope)
4bd8800e 2969 free_bindings (&lease -> scope, file, line);
fb6297b1
TL
2970 if (lease -> uid != lease -> uid_buf) {
2971 dfree (lease -> uid, file, line);
2972 lease -> uid = (unsigned char *)0;
2973 }
6c8a5472
TL
2974}
2975
f63b4929
TL
2976/* Look through all the pools in a list starting with the specified pool
2977 for a free lease. We try to find a virgin lease if we can. If we
2978 don't find a virgin lease, we try to find a non-virgin lease that's
2979 free. If we can't find one of those, we try to reclaim an abandoned
2980 lease. If all of these possibilities fail to pan out, we don't return
2981 a lease at all. */
2982
20916cae
TL
2983int allocate_lease (struct lease **lp, struct packet *packet,
2984 struct pool *pool, int *peer_has_leases)
f63b4929 2985{
20916cae 2986 struct lease *lease = (struct lease *)0;
f63b4929
TL
2987 struct permit *permit;
2988
2989 if (!pool)
20916cae 2990 return 0;
f63b4929
TL
2991
2992 /* If we aren't elegible to try this pool, try a subsequent one. */
2993 if ((pool -> prohibit_list &&
2994 permitted (packet, pool -> prohibit_list)) ||
2995 (pool -> permit_list && !permitted (packet, pool -> permit_list)))
20916cae 2996 return allocate_lease (lp, packet, pool -> next,
33225687 2997 peer_has_leases);
f63b4929
TL
2998
2999 lease = pool -> last_lease;
3000
2cbc0e48 3001#if defined (FAILOVER_PROTOCOL)
33225687
TL
3002 /* Peer_has_leases just says that we found at least one free lease.
3003 If no free lease is returned, the caller can deduce that this
3004 means the peer is hogging all the free leases, so we can print
3005 a better error message. */
3006 if (lease)
3007 *peer_has_leases = 1;
3008
2cbc0e48
TL
3009 /* XXX Do we need code here to ignore PEER_IS_OWNER and just check
3010 XXX tstp if we're in, e.g., PARTNER_DOWN? Where do we deal with
3011 XXX CONFLICT_DETECTED, et al? */
3012 /* Skip to the most expired lease in the pool that is not owned by a
3013 failover peer. */
3014 if (lease -> pool && lease -> pool -> failover_peer) {
33225687
TL
3015 while (lease &&
3016 (lease -> flags & PEER_IS_OWNER) &&
2cbc0e48
TL
3017 (lease -> ends <=
3018 cur_time + lease -> pool -> failover_peer -> mclt))
3019 lease = lease -> prev;
33225687
TL
3020 /* We didn't find an unexpired lease that we own? */
3021 if (lease && lease -> flags & PEER_IS_OWNER)
3022 lease = (struct lease *)0;
2cbc0e48
TL
3023 }
3024#endif
3025
f63b4929
TL
3026 /* If there are no leases in the pool that have
3027 expired, try the next one. */
3028 if (!lease || lease -> ends > cur_time)
20916cae
TL
3029 return allocate_lease (lp, packet,
3030 pool -> next, peer_has_leases);
f63b4929
TL
3031
3032 /* If we find an abandoned lease, and no other lease qualifies
3033 better, take it. */
2cbc0e48
TL
3034 /* XXX what if there are non-abandoned leases that are younger
3035 XXX than this? Shouldn't we hunt for those here? */
0af446bc 3036 if ((lease -> flags & ABANDONED_LEASE)) {
f63b4929
TL
3037 /* If we already have a non-abandoned lease that we didn't
3038 love, but that's okay, don't reclaim the abandoned lease. */
20916cae
TL
3039 if (*lp)
3040 return allocate_lease (lp, packet, pool -> next,
3041 peer_has_leases);
3042 if (!allocate_lease (lp, packet,
3043 pool -> next, peer_has_leases)) {
8ae2d595 3044 log_error ("Reclaiming abandoned IP address %s.",
f63b4929
TL
3045 piaddr (lease -> ip_addr));
3046 lease -> flags &= ~ABANDONED_LEASE;
20916cae 3047 lease_reference (lp, lease, MDL);
f63b4929 3048 }
20916cae 3049 return 1;
f63b4929
TL
3050 }
3051
3052 /* If there's a lease we could take, but it had previously been
3053 allocated to a different client, try for a virgin lease before
3054 stealing it. */
3055 if (lease -> uid_len || lease -> hardware_addr.hlen) {
3056 /* If we're already in that boat, no need to consider
3057 allocating this particular lease. */
20916cae
TL
3058 if (*lp)
3059 return allocate_lease (lp, packet, pool -> next,
3060 peer_has_leases);
f63b4929 3061
20916cae
TL
3062 allocate_lease (lp, packet, pool -> next, peer_has_leases);
3063 if (*lp)
3064 return 1;
f63b4929
TL
3065 }
3066
20916cae
TL
3067 lease_reference (lp, lease, MDL);
3068 return 1;
f63b4929
TL
3069}
3070
3071/* Determine whether or not a permit exists on a particular permit list
3072 that matches the specified packet, returning nonzero if so, zero if
3073 not. */
3074
3075int permitted (packet, permit_list)
3076 struct packet *packet;
3077 struct permit *permit_list;
3078{
3079 struct permit *p;
3080 int i;
3081
3082 for (p = permit_list; p; p = p -> next) {
3083 switch (p -> type) {
3084 case permit_unknown_clients:
3085 if (!packet -> known)
3086 return 1;
3087 break;
3088
3089 case permit_known_clients:
3090 if (packet -> known)
3091 return 1;
3092 break;
3093
3094 case permit_authenticated_clients:
3095 if (packet -> authenticated)
3096 return 1;
3097 break;
3098
3099 case permit_unauthenticated_clients:
3100 if (!packet -> authenticated)
3101 return 1;
3102 break;
3103
3104 case permit_all_clients:
3105 return 1;
3106
3107 case permit_dynamic_bootp_clients:
3108 if (!packet -> options_valid ||
3109 !packet -> packet_type)
3110 return 1;
3111 break;
3112
3113 case permit_class:
00855426 3114 for (i = 0; i < packet -> class_count; i++) {
f63b4929
TL
3115 if (p -> class == packet -> classes [i])
3116 return 1;
00855426
TL
3117 if (packet -> classes [i] &&
3118 packet -> classes [i] -> superclass &&
3119 (packet -> classes [i] -> superclass ==
3120 p -> class))
3121 return 1;
3122 }
f63b4929
TL
3123 break;
3124 }
3125 }
3126 return 0;
3127}
3128
e2c5cba2
TL
3129int locate_network (packet)
3130 struct packet *packet;
3131{
3132 struct iaddr ia;
1a634d56 3133 struct data_string data;
20916cae 3134 struct subnet *subnet = (struct subnet *)0;
1a634d56 3135 struct option_cache *oc;
e2c5cba2 3136
1a634d56
TL
3137 /* See if there's a subnet selection option. */
3138 oc = lookup_option (&dhcp_universe, packet -> options,
3139 DHO_SUBNET_SELECTION);
3140
3141 /* If there's no SSO and no giaddr, then use the shared_network
3142 from the interface, if there is one. If not, fail. */
3143 if (!oc && !packet -> raw -> giaddr.s_addr) {
20916cae
TL
3144 if (packet -> interface -> shared_network) {
3145 shared_network_reference
3146 (&packet -> shared_network,
3147 packet -> interface -> shared_network, MDL);
1a634d56 3148 return 1;
20916cae 3149 }
1a634d56
TL
3150 return 0;
3151 }
3152
3153 /* If there's an SSO, and it's valid, use it to figure out the
3154 subnet. If it's not valid, fail. */
3155 if (oc) {
3156 memset (&data, 0, sizeof data);
3157 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
3158 packet -> options,
3159 (struct option_state *)0,
3160 &global_scope, oc, MDL)) {
1a634d56
TL
3161 return 0;
3162 }
3163 if (data.len != 4) {
1a634d56
TL
3164 return 0;
3165 }
3166 ia.len = 4;
3167 memcpy (ia.iabuf, data.data, 4);
3168 data_string_forget (&data, MDL);
e2c5cba2 3169 } else {
1a634d56
TL
3170 ia.len = 4;
3171 memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
e2c5cba2 3172 }
1a634d56
TL
3173
3174 /* If we know the subnet on which the IP address lives, use it. */
20916cae
TL
3175 if (find_subnet (&subnet, ia, MDL)) {
3176 shared_network_reference (&packet -> shared_network,
3177 subnet -> shared_network, MDL);
3178 subnet_dereference (&subnet, MDL);
e2c5cba2 3179 return 1;
1a634d56
TL
3180 }
3181
3182 /* Otherwise, fail. */
e2c5cba2
TL
3183 return 0;
3184}
5b558f0d
TL
3185
3186/* Parse a Relay Agent Information option and put it at the end of the
3187 list of such options on the specified packet. */
3188
3189int parse_agent_information_option (packet, len, data)
3190 struct packet *packet;
3191 int len;
3192 u_int8_t *data;
3193{
3194 struct agent_options *a, **tail;
3195 struct option_tag *t, *oth = 0, **ott = &oth;
3196 u_int8_t *op = data, *max = data + len;
3197
3198 /* Parse the agent information option suboptions. */
3199 while (op < max) {
3200 /* Check for overflow. */
3201 if (op + 1 == max || op + op [1] + 2 > max)
3202 return 0;
3203 /* Make space for this suboption. */
3204 t = (struct option_tag *)
4bd8800e 3205 dmalloc (op [1] + 1 + sizeof *t, MDL);
5b558f0d
TL
3206 if (!t)
3207 log_fatal ("no memory for option tag data.");
3208
3209 /* Link it in at the tail of the list. */
3210 t -> next = (struct option_tag *)0;
3211 *ott = t;
3212 ott = &t -> next;
3213
3214 /* Copy the option data in in its raw form. */
3215 memcpy (t -> data, op, (unsigned)(op [1] + 2));
3216 op += op [1] + 2;
3217 }
3218
3219 /* Make an agent options structure to put on the list. */
4bd8800e 3220 a = (struct agent_options *)dmalloc (sizeof *a, MDL);
5b558f0d
TL
3221 if (!a)
3222 log_fatal ("can't allocate space for agent option structure.");
3223
3224 /* Find the tail of the list. */
3225 for (tail = ((struct agent_options **)
3226 &packet -> options -> universes [agent_universe.index]);
3227 *tail; tail = &((*tail) -> next))
3228 ;
3229 *tail = a;
3230 a -> next = (struct agent_options *)0;
3231 a -> first = oth;
3232 a -> length = len;
3233
3234 return 1;
3235}
3236
3237unsigned cons_agent_information_options (cfg_options, outpacket,
3238 agentix, length)
3239 struct option_state *cfg_options;
3240 struct dhcp_packet *outpacket;
3241 unsigned agentix;
3242 unsigned length;
3243{
3244 /* We tack any agent options onto the end of the packet after
3245 we've put it together. */
3246 if (cfg_options -> universe_count > agent_universe.index &&
3247 cfg_options -> universes [agent_universe.index]) {
3248 int len = 0;
3249 struct agent_options *a;
3250 struct option_tag *o;
3251
3252 /* Cycle through the options, appending them to the
3253 buffer. */
3254 for (a = ((struct agent_options *)
3255 cfg_options -> universes [agent_universe.index]);
3256 a; a = a -> next) {
3257 if (agentix + a -> length + 3 + DHCP_FIXED_LEN <=
3258 dhcp_max_agent_option_packet_length) {
3259 outpacket -> options [agentix++]
3260 = DHO_DHCP_AGENT_OPTIONS;
3261 outpacket -> options [agentix++] = a -> length;
3262 for (o = a -> first; o; o = o -> next) {
3263 memcpy (&outpacket -> options [agentix],
3264 o -> data,
3265 (unsigned)(o -> data [1] + 2));
3266 agentix += o -> data [1] + 2;
3267 }
3268 }
3269 }
3270
3271 /* Reterminate the packet. */
3272 outpacket -> options [agentix++] = DHO_END;
3273
3274 /* Recompute the length, which may now be higher than the
3275 client can accept but should be okay for the relay agent. */
3276 return agentix + DHCP_FIXED_NON_UDP;
3277 }
3278
3279 return length;
3280}