]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/dhcp.c
Don't try to respond to packets if we can't figure where they came from; add support...
[thirdparty/dhcp.git] / server / dhcp.c
CommitLineData
d7837182
TL
1/* dhcp.c
2
b88e8e15 3 DHCP Protocol engine. */
d7837182
TL
4
5/*
b88e8e15
TL
6 * Copyright (c) 1995, 1996 The Internet Software Consortium.
7 * All rights reserved.
d7837182
TL
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
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.
21 *
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 <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises. To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''. To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
41 */
42
43#ifndef lint
44static char copyright[] =
20581a0b 45"@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
d7837182
TL
46#endif /* not lint */
47
48#include "dhcpd.h"
49
d3e5a892 50static unsigned char dhcp_message [256];
b88e8e15 51
d7837182
TL
52void dhcp (packet)
53 struct packet *packet;
54{
3a581108
TL
55 if (!locate_network (packet))
56 return;
57
ed8bcd8f
TL
58 switch (packet -> packet_type) {
59 case DHCPDISCOVER:
60 dhcpdiscover (packet);
61 break;
97ca1699 62
ed8bcd8f
TL
63 case DHCPREQUEST:
64 dhcprequest (packet);
65 break;
97ca1699 66
ed8bcd8f
TL
67 case DHCPRELEASE:
68 dhcprelease (packet);
69 break;
97ca1699 70
b88e8e15
TL
71 case DHCPDECLINE:
72 dhcpdecline (packet);
73 break;
74
75 case DHCPINFORM:
76 dhcpinform (packet);
77 break;
78
ed8bcd8f
TL
79 default:
80 break;
97ca1699 81 }
ed8bcd8f 82}
97ca1699 83
ed8bcd8f
TL
84void dhcpdiscover (packet)
85 struct packet *packet;
86{
15c00bba 87 struct lease *lease = find_lease (packet, packet -> shared_network);
7a049f2c 88 struct host_decl *hp;
97ca1699 89
a69f4fd3 90 note ("DHCPDISCOVER from %s via %s",
f9a32ee9
TL
91 print_hw_addr (packet -> raw -> htype,
92 packet -> raw -> hlen,
a69f4fd3
TL
93 packet -> raw -> chaddr),
94 packet -> raw -> giaddr.s_addr
95 ? inet_ntoa (packet -> raw -> giaddr)
96 : packet -> interface -> name);
a8b53b42 97
15c00bba
TL
98 /* Sourceless packets don't make sense here. */
99 if (!packet -> shared_network) {
100 note ("Packet from unknown subnet: %s",
101 inet_ntoa (packet -> raw -> giaddr));
102 return;
103 }
104
97ca1699
TL
105 /* If we didn't find a lease, try to allocate one... */
106 if (!lease) {
7a049f2c 107 lease = packet -> shared_network -> last_lease;
97ca1699
TL
108
109 /* If there are no leases in that subnet that have
110 expired, we have nothing to offer this client. */
faf4a8de 111 if (!lease || lease -> ends > cur_time) {
97ca1699 112 note ("no free leases on subnet %s",
7a049f2c 113 packet -> shared_network -> name);
97ca1699
TL
114 return;
115 }
7a049f2c
TL
116
117 /* Try to find a host_decl that matches the client
118 identifier or hardware address on the packet, and
119 has no fixed IP address. If there is one, hang
120 it off the lease so that its option definitions
121 can be used. */
122 if (((packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len
123 != 0) &&
124 ((hp = find_hosts_by_uid
125 (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data,
126 packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len))
127 != (struct host_decl *)0)) ||
128 ((hp = find_hosts_by_haddr (packet -> raw -> htype,
129 packet -> raw -> chaddr,
130 packet -> raw -> hlen))
131 != (struct host_decl *)0)) {
132 for (; hp; hp = hp -> n_ipaddr) {
133 if (!hp -> fixed_addr) {
134 lease -> host = hp;
135 break;
136 }
137 }
138 } else {
139 lease -> host = (struct host_decl *)0;
140 }
97ca1699
TL
141 }
142
ed8bcd8f
TL
143 ack_lease (packet, lease, DHCPOFFER, cur_time + 120);
144}
145
146void dhcprequest (packet)
147 struct packet *packet;
148{
15c00bba 149 struct lease *lease;
b88e8e15 150 struct iaddr cip;
7a049f2c 151 struct subnet *subnet;
b88e8e15 152
b88e8e15
TL
153 if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) {
154 cip.len = 4;
155 memcpy (cip.iabuf,
156 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data,
157 4);
a8b53b42
TL
158 } else {
159 cip.len = 4;
160 memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
161 }
162
15c00bba
TL
163 /* Find the lease that matches the address requested by the
164 client. */
165 subnet = find_subnet (cip);
166 lease = find_lease (packet, (subnet
167 ? subnet -> shared_network
168 : (struct shared_network *)0));
169
a69f4fd3 170 note ("DHCPREQUEST for %s from %s via %s",
7a049f2c
TL
171 piaddr (cip),
172 print_hw_addr (packet -> raw -> htype,
173 packet -> raw -> hlen,
a69f4fd3
TL
174 packet -> raw -> chaddr),
175 packet -> raw -> giaddr.s_addr
176 ? inet_ntoa (packet -> raw -> giaddr)
177 : packet -> interface -> name);
178
a8b53b42 179
15c00bba
TL
180 /* If a client on a given network wants to request a lease on
181 an address on a different network, NAK it. If the Requested
182 Address option was used, the protocol says that it must have
183 been broadcast, so we can trust the source network information.
184
185 If ciaddr was specified and Requested Address was not, then
186 we really only know for sure what network a packet came from
187 if it came through a BOOTP gateway - if it came through an
188 IP router, we'll just have to assume that it's cool.
189
190 This violates the protocol spec in the case that the client
191 is in the REBINDING state and broadcasts a DHCPREQUEST on
192 the local wire. We're supposed to check ciaddr for
193 validity in that case, but if the packet was unicast
194 through a router from a client in the RENEWING state, it
195 would look exactly the same to us and it would be very
196 bad to send a DHCPNAK. I think we just have to live with
197 this. */
198 if ((packet -> raw -> ciaddr.s_addr &&
199 packet -> raw -> giaddr.s_addr) ||
200 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) {
201
202 /* If we don't know where it came from but we do know
203 where it claims to have come from, it didn't come
204 from there. Fry it. */
205 if (!packet -> shared_network) {
206 subnet = find_subnet (cip);
207 if (subnet) {
208 nak_lease (packet, &cip);
209 return;
210 }
b88e8e15 211 }
15c00bba
TL
212
213 /* If we do know where it came from and we don't know
214 where it claims to have come from, same deal - fry it. */
7a049f2c
TL
215 subnet = find_grouped_subnet (packet -> shared_network, cip);
216 if (!subnet) {
a8b53b42 217 nak_lease (packet, &cip);
b88e8e15
TL
218 return;
219 }
220 }
ed8bcd8f 221
d01578b7
TL
222 /* If we own the lease that the client is asking for,
223 and it's already been assigned to the client, ack it. */
224 if (lease &&
225 ((lease -> uid_len && lease -> uid_len ==
226 packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len &&
227 !memcmp (packet -> options
228 [DHO_DHCP_CLIENT_IDENTIFIER].data,
229 lease -> uid, lease -> uid_len)) ||
230 (lease -> hardware_addr.hlen == packet -> raw -> hlen &&
231 lease -> hardware_addr.htype == packet -> raw -> htype &&
232 !memcmp (lease -> hardware_addr.haddr,
233 packet -> raw -> chaddr,
234 packet -> raw -> hlen)))) {
235 ack_lease (packet, lease, DHCPACK, 0);
236 return;
237 }
7a049f2c 238
d01578b7
TL
239 /* Otherwise, if we have a lease for this client,
240 release it, and in any case don't reply to the
241 DHCPREQUEST. */
242 if (packet -> options [DHO_DHCP_SERVER_IDENTIFIER].len
243 && memcmp (packet ->
244 options [DHO_DHCP_SERVER_IDENTIFIER].data,
245 server_identifier.iabuf,
246 server_identifier.len)) {
247 if (lease)
248 release_lease (lease);
249 return;
ed8bcd8f 250 }
ed8bcd8f
TL
251}
252
253void dhcprelease (packet)
254 struct packet *packet;
255{
15c00bba 256 struct lease *lease = find_lease (packet, packet -> shared_network);
ed8bcd8f 257
a69f4fd3 258 note ("DHCPRELEASE of %s from %s via %s",
7a049f2c 259 inet_ntoa (packet -> raw -> ciaddr),
f9a32ee9
TL
260 print_hw_addr (packet -> raw -> htype,
261 packet -> raw -> hlen,
a69f4fd3
TL
262 packet -> raw -> chaddr),
263 packet -> raw -> giaddr.s_addr
264 ? inet_ntoa (packet -> raw -> giaddr)
265 : packet -> interface -> name);
266
a8b53b42 267
b88e8e15 268 /* If we found a lease, release it. */
ed8bcd8f
TL
269 if (lease) {
270 release_lease (lease);
271 }
272}
273
b88e8e15
TL
274void dhcpdecline (packet)
275 struct packet *packet;
276{
15c00bba 277 struct lease *lease = find_lease (packet, packet -> shared_network);
a8b53b42
TL
278 struct iaddr cip;
279
280 if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) {
281 cip.len = 4;
282 memcpy (cip.iabuf,
283 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data,
284 4);
285 } else {
286 cip.len = 0;
287 }
288
a69f4fd3 289 note ("DHCPDECLINE on %s from %s via %s",
7a049f2c 290 piaddr (cip),
f9a32ee9
TL
291 print_hw_addr (packet -> raw -> htype,
292 packet -> raw -> hlen,
a69f4fd3
TL
293 packet -> raw -> chaddr),
294 packet -> raw -> giaddr.s_addr
295 ? inet_ntoa (packet -> raw -> giaddr)
296 : packet -> interface -> name);
297
b88e8e15
TL
298
299 /* If we found a lease, mark it as unusable and complain. */
300 if (lease) {
301 abandon_lease (lease);
302 }
303}
304
305void dhcpinform (packet)
306 struct packet *packet;
307{
7a049f2c 308 note ("DHCPINFORM from %s",
f9a32ee9 309 inet_ntoa (packet -> raw -> ciaddr));
b88e8e15
TL
310}
311
a8b53b42 312void nak_lease (packet, cip)
ed8bcd8f 313 struct packet *packet;
a8b53b42 314 struct iaddr *cip;
ed8bcd8f
TL
315{
316 struct sockaddr_in to;
317 int result;
318 struct dhcp_packet raw;
319 unsigned char nak = DHCPNAK;
320 struct packet outgoing;
fde927d2 321 struct hardware hto;
ed8bcd8f
TL
322
323 struct tree_cache *options [256];
324 struct tree_cache dhcpnak_tree;
b88e8e15 325 struct tree_cache dhcpmsg_tree;
ed8bcd8f
TL
326
327 memset (options, 0, sizeof options);
328 memset (&outgoing, 0, sizeof outgoing);
329 memset (&raw, 0, sizeof raw);
330 outgoing.raw = &raw;
331
332 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
333 options [DHO_DHCP_MESSAGE_TYPE] = &dhcpnak_tree;
334 options [DHO_DHCP_MESSAGE_TYPE] -> value = &nak;
335 options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof nak;
336 options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof nak;
337 options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
338 options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
339
b88e8e15
TL
340 /* Set DHCP_MESSAGE to whatever the message is */
341 options [DHO_DHCP_MESSAGE] = &dhcpmsg_tree;
342 options [DHO_DHCP_MESSAGE] -> value = dhcp_message;
343 options [DHO_DHCP_MESSAGE] -> len = strlen (dhcp_message);
344 options [DHO_DHCP_MESSAGE] -> buf_size = strlen (dhcp_message);
345 options [DHO_DHCP_MESSAGE] -> timeout = 0xFFFFFFFF;
346 options [DHO_DHCP_MESSAGE] -> tree = (struct tree *)0;
347
348 /* Do not use the client's requested parameter list. */
349 packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].len = 0;
350 packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data =
351 (unsigned char *)0;
352
ed8bcd8f
TL
353 /* Set up the option buffer... */
354 cons_options (packet, &outgoing, options, 0);
355
b88e8e15 356/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
7a049f2c 357 memcpy (&raw.siaddr, server_identifier.iabuf, 4);
ed8bcd8f 358 raw.giaddr = packet -> raw -> giaddr;
b88e8e15
TL
359 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
360 raw.hlen = packet -> raw -> hlen;
361 raw.htype = packet -> raw -> htype;
ed8bcd8f
TL
362
363 raw.xid = packet -> raw -> xid;
364 raw.secs = packet -> raw -> secs;
b88e8e15 365 raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
ed8bcd8f
TL
366 raw.hops = packet -> raw -> hops;
367 raw.op = BOOTREPLY;
368
7a049f2c 369 /* Report what we're sending... */
a69f4fd3 370 note ("DHCPNAK on %s to %s via %s",
7a049f2c
TL
371 piaddr (*cip),
372 print_hw_addr (packet -> raw -> htype,
373 packet -> raw -> hlen,
a69f4fd3
TL
374 packet -> raw -> chaddr),
375 packet -> raw -> giaddr.s_addr
376 ? inet_ntoa (packet -> raw -> giaddr)
377 : packet -> interface -> name);
378
379
7a049f2c
TL
380
381#ifdef DEBUG_PACKET
382 dump_packet (packet);
383 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
384 dump_packet (&outgoing);
385 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
386#endif
387
388 hto.htype = packet -> raw -> htype;
389 hto.hlen = packet -> raw -> hlen;
390 memcpy (hto.haddr, packet -> raw -> chaddr, hto.hlen);
391
392 /* Set up the common stuff... */
393 to.sin_family = AF_INET;
394#ifdef HAVE_SA_LEN
395 to.sin_len = sizeof to;
396#endif
397 memset (to.sin_zero, 0, sizeof to.sin_zero);
398
b88e8e15
TL
399 /* If this was gatewayed, send it back to the gateway.
400 Otherwise, broadcast it on the local network. */
401 if (raw.giaddr.s_addr) {
ed8bcd8f 402 to.sin_addr = raw.giaddr;
b88e8e15 403 to.sin_port = server_port;
7a049f2c 404
8ec97099
TL
405 if (outgoing.packet_length < BOOTP_MIN_LEN)
406 outgoing.packet_length = BOOTP_MIN_LEN;
407
7a049f2c
TL
408#ifdef USE_FALLBACK
409 result = send_fallback (&fallback_interface,
410 packet, &raw, outgoing.packet_length,
411 raw.siaddr, &to, &hto);
412 if (result < 0)
413 warn ("send_fallback: %m");
414 return;
415#endif
b88e8e15 416 } else {
fde927d2 417 to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
a8b53b42 418 to.sin_port = packet->client_port;
b88e8e15 419 }
ed8bcd8f 420
ed8bcd8f 421 errno = 0;
fde927d2
TL
422 result = send_packet (packet -> interface,
423 packet, &raw, outgoing.packet_length,
7a049f2c 424 raw.siaddr, &to, (struct hardware *)0);
ed8bcd8f 425 if (result < 0)
7a049f2c 426 warn ("send_packet: %m");
ed8bcd8f
TL
427}
428
429void ack_lease (packet, lease, offer, when)
430 struct packet *packet;
431 struct lease *lease;
432 unsigned char offer;
433 TIME when;
434{
435 struct lease lt;
436 TIME lease_time;
437
438 int bufs = 0;
439 struct packet outgoing;
440 struct dhcp_packet raw;
441 struct tree_cache *options [256];
442 struct sockaddr_in to;
fde927d2 443 struct hardware hto;
ed8bcd8f
TL
444 int result;
445
446 struct tree_cache dhcpoffer_tree;
447 unsigned char lease_time_buf [4];
448 struct tree_cache lease_time_tree;
449 struct tree_cache server_id_tree;
b88e8e15
TL
450 struct tree_cache vendor_class_tree;
451 struct tree_cache user_class_tree;
452
453 struct class *vendor_class, *user_class;
454 char *filename;
7a049f2c 455 char *server_name;
b88e8e15
TL
456 int i;
457
458 if (packet -> options [DHO_DHCP_CLASS_IDENTIFIER].len) {
459 vendor_class =
460 find_class (0,
461 packet ->
462 options [DHO_DHCP_CLASS_IDENTIFIER].data,
463 packet ->
464 options [DHO_DHCP_CLASS_IDENTIFIER].len);
465 } else {
466 vendor_class = (struct class *)0;
467 }
468
469 if (packet -> options [DHO_DHCP_USER_CLASS_ID].len) {
470 user_class =
471 find_class (0,
472 packet ->
473 options [DHO_DHCP_USER_CLASS_ID].data,
474 packet ->
475 options [DHO_DHCP_USER_CLASS_ID].len);
476 } else {
477 user_class = (struct class *)0;
478 }
479
7a049f2c
TL
480 /* Choose a filename; first from the host_decl, if any, then from
481 the user class, then from the vendor class. */
acf6cfe3 482 if (lease -> host && lease -> host -> filename)
7a049f2c
TL
483 filename = lease -> host -> filename;
484 else if (user_class && user_class -> filename)
b88e8e15
TL
485 filename = user_class -> filename;
486 else if (vendor_class && vendor_class -> filename)
487 filename = vendor_class -> filename;
488 else filename = (char *)0;
ed8bcd8f 489
7a049f2c 490 /* Choose a server name as above. */
acf6cfe3 491 if (lease -> host && lease -> host -> server_name)
7a049f2c
TL
492 server_name = lease -> host -> server_name;
493 else if (user_class && user_class -> server_name)
494 server_name = user_class -> server_name;
495 else if (vendor_class && vendor_class -> server_name)
496 server_name = vendor_class -> server_name;
497 else server_name = (char *)0;
498
97ca1699
TL
499 /* At this point, we have a lease that we can offer the client.
500 Now we construct a lease structure that contains what we want,
501 and call supersede_lease to do the right thing with it. */
502
503 memset (&lt, 0, sizeof lt);
504
505 /* Use the ip address of the lease that we finally found in
506 the database. */
507 lt.ip_addr = lease -> ip_addr;
508
509 /* Start now. */
510 lt.starts = cur_time;
511
7a049f2c
TL
512 /* Figure out how long a lease to assign. If this is a
513 dynamic BOOTP lease, its duration must be infinite. */
514 if (offer) {
515 if (packet -> options [DHO_DHCP_LEASE_TIME].len == 4) {
516 lease_time = getULong
517 (packet -> options [DHO_DHCP_LEASE_TIME].data);
518
519 /* Don't let the client ask for a longer lease than
520 is supported for this subnet or host. */
521 if (lease -> host && lease -> host -> max_lease_time) {
522 if (lease_time >
523 lease -> host -> max_lease_time)
524 lease_time = (lease -> host ->
525 max_lease_time);
526 } else {
527 if (lease_time >
528 lease -> subnet -> max_lease_time)
529 lease_time = (lease -> subnet ->
530 max_lease_time);
531 }
532 } else {
533 if (lease -> host
534 && lease -> host -> default_lease_time)
535 lease_time = (lease -> host ->
536 default_lease_time);
537 else
538 lease_time = (lease -> subnet ->
539 default_lease_time);
540 }
541
542 lt.offered_expiry = cur_time + lease_time;
543 if (when)
544 lt.ends = when;
545 else
546 lt.ends = lt.offered_expiry;
547 } else {
548 lt.offered_expiry = lt.ends = MAX_TIME;
549 lt.flags = BOOTP_LEASE;
550 }
97ca1699
TL
551
552 lt.timestamp = cur_time;
553
554 /* Record the uid, if given... */
555 if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) {
556 lt.uid_len =
557 packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len;
558 lt.uid = packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data;
559 packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data =
560 (unsigned char *)0;
561 packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len = 0;
562 }
563
564 /* Record the hardware address, if given... */
565 lt.hardware_addr.hlen = packet -> raw -> hlen;
566 lt.hardware_addr.htype = packet -> raw -> htype;
567 memcpy (lt.hardware_addr.haddr, packet -> raw -> chaddr,
568 packet -> raw -> hlen);
569
7a049f2c
TL
570 lt.host = lease -> host;
571 lt.subnet = lease -> subnet;
572 lt.shared_network = lease -> shared_network;
97ca1699
TL
573
574 /* Record the transaction id... */
575 lt.xid = packet -> raw -> xid;
576
7a049f2c
TL
577 /* Don't call supersede_lease on a mocked-up lease. */
578 if (lease -> flags & STATIC_LEASE)
579 ;
580 else
1358b874 581 /* Install the new information about this lease in the database.
7a049f2c
TL
582 If this is a DHCPACK or a dynamic BOOTREPLY and we can't write
583 the lease, don't ACK it (or BOOTREPLY it) either. */
584 if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK)
585 || (offer && offer != DHCPACK)))
586 return;
97ca1699
TL
587
588 /* Send a response to the client... */
685963dc
TL
589
590 memset (&outgoing, 0, sizeof outgoing);
591 memset (&raw, 0, sizeof raw);
592 outgoing.raw = &raw;
593
594 /* Copy in the filename if given; otherwise, flag the filename
595 buffer as available for options. */
b88e8e15
TL
596 if (filename)
597 strncpy (raw.file, filename, sizeof raw.file);
598 else
599 bufs |= 1;
685963dc
TL
600
601 /* Copy in the server name if given; otherwise, flag the
602 server_name buffer as available for options. */
7a049f2c
TL
603 if (server_name)
604 strncpy (raw.sname, server_name, sizeof raw.sname);
605 else
606 bufs |= 2; /* XXX */
685963dc
TL
607
608 memcpy (raw.chaddr, packet -> raw -> chaddr, packet -> raw -> hlen);
609 raw.hlen = packet -> raw -> hlen;
610 raw.htype = packet -> raw -> htype;
611
612 /* Start out with the subnet options... */
7a049f2c
TL
613 memcpy (options, lease -> subnet -> options, sizeof options);
614
615 /* Vendor and user classes are only supported for DHCP clients. */
616 if (offer) {
617 /* If we have a vendor class, install those options,
618 superseding any subnet options. */
619 if (vendor_class) {
620 for (i = 0; i < 256; i++)
621 if (vendor_class -> options [i])
622 options [i] =
623 vendor_class -> options [i];
624 }
685963dc 625
7a049f2c
TL
626 /* If we have a user class, install those options,
627 superseding any subnet and vendor class options. */
628 if (user_class) {
629 for (i = 0; i < 256; i++)
630 if (user_class -> options [i])
631 options [i] =
632 user_class -> options [i];
633 }
b88e8e15 634
b88e8e15
TL
635 }
636
7a049f2c
TL
637 /* If we have a host_decl structure, install the associated
638 options, superseding anything that's in the way. */
639 if (lease -> host) {
640 for (i = 0; i < 256; i++)
641 if (lease -> host -> options [i])
642 options [i] = lease -> host -> options [i];
b88e8e15
TL
643 }
644
7a049f2c
TL
645 /* Now, if appropriate, put in DHCP-specific options that
646 override those. */
647 if (offer) {
648 options [DHO_DHCP_MESSAGE_TYPE] = &dhcpoffer_tree;
649 options [DHO_DHCP_MESSAGE_TYPE] -> value = &offer;
650 options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof offer;
651 options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof offer;
652 options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
653 options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
654
655 options [DHO_DHCP_SERVER_IDENTIFIER] = &server_id_tree;
656 options [DHO_DHCP_SERVER_IDENTIFIER] ->
657 value = server_identifier.iabuf;
658 options [DHO_DHCP_SERVER_IDENTIFIER] ->
659 len = server_identifier.len;
660 options [DHO_DHCP_SERVER_IDENTIFIER] ->
661 buf_size = server_identifier.len;
662 options [DHO_DHCP_SERVER_IDENTIFIER] ->
663 timeout = 0xFFFFFFFF;
664 options [DHO_DHCP_SERVER_IDENTIFIER] ->
665 tree = (struct tree *)0;
666
667 /* Sanity check the lease time. */
668 if ((lease->offered_expiry - cur_time) < 0)
669 putULong (lease_time_buf,
670 lease -> subnet -> default_lease_time);
671 else if (lease -> offered_expiry - cur_time >
672 lease -> subnet -> max_lease_time)
673 putULong (lease_time_buf,
674 lease -> subnet -> max_lease_time);
675 else
676 putULong (lease_time_buf,
677 lease -> offered_expiry - cur_time);
b88e8e15 678
20581a0b 679 putULong (lease_time_buf, lease -> offered_expiry - cur_time);
7a049f2c
TL
680 options [DHO_DHCP_LEASE_TIME] = &lease_time_tree;
681 options [DHO_DHCP_LEASE_TIME] -> value = lease_time_buf;
682 options [DHO_DHCP_LEASE_TIME] -> len = sizeof lease_time_buf;
683 options [DHO_DHCP_LEASE_TIME] ->
684 buf_size = sizeof lease_time_buf;
685 options [DHO_DHCP_LEASE_TIME] -> timeout = 0xFFFFFFFF;
686 options [DHO_DHCP_LEASE_TIME] -> tree = (struct tree *)0;
687
688 /* If we used the vendor class the client specified, we
689 have to return it. */
690 if (vendor_class) {
691 options [DHO_DHCP_CLASS_IDENTIFIER] =
692 &vendor_class_tree;
693 options [DHO_DHCP_CLASS_IDENTIFIER] ->
694 value = (unsigned char *)vendor_class -> name;
695 options [DHO_DHCP_CLASS_IDENTIFIER] ->
696 len = strlen (vendor_class -> name);
697 options [DHO_DHCP_CLASS_IDENTIFIER] ->
698 buf_size = strlen (vendor_class -> name);
699 options [DHO_DHCP_CLASS_IDENTIFIER] ->
700 timeout = 0xFFFFFFFF;
701 options [DHO_DHCP_CLASS_IDENTIFIER] ->
702 tree = (struct tree *)0;
703 }
a8b53b42 704
7a049f2c
TL
705 /* If we used the user class the client specified, we
706 have to return it. */
707 if (user_class) {
708 options [DHO_DHCP_USER_CLASS_ID] = &user_class_tree;
709 options [DHO_DHCP_USER_CLASS_ID] ->
710 value = (unsigned char *)user_class -> name;
711 options [DHO_DHCP_USER_CLASS_ID] ->
712 len = strlen (user_class -> name);
713 options [DHO_DHCP_USER_CLASS_ID] ->
714 buf_size = strlen (user_class -> name);
715 options [DHO_DHCP_USER_CLASS_ID] ->
716 timeout = 0xFFFFFFFF;
717 options [DHO_DHCP_USER_CLASS_ID] ->
718 tree = (struct tree *)0;
719 }
720 }
685963dc
TL
721
722 cons_options (packet, &outgoing, options, bufs);
8ec97099
TL
723 if (!offer && outgoing.packet_length < BOOTP_MIN_LEN)
724 outgoing.packet_length = BOOTP_MIN_LEN;
685963dc
TL
725
726 raw.ciaddr = packet -> raw -> ciaddr;
727 memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
7a049f2c
TL
728 if (lease -> subnet -> interface_address.len)
729 memcpy (&raw.siaddr,
730 lease -> subnet -> interface_address.iabuf, 4);
731 else
732 memcpy (&raw.siaddr, server_identifier.iabuf, 4);
733
685963dc
TL
734 raw.giaddr = packet -> raw -> giaddr;
735
736 raw.xid = packet -> raw -> xid;
737 raw.secs = packet -> raw -> secs;
738 raw.flags = packet -> raw -> flags;
739 raw.hops = packet -> raw -> hops;
740 raw.op = BOOTREPLY;
741
7a049f2c 742 /* Say what we're doing... */
a69f4fd3 743 note ("%s on %s to %s via %s",
7a049f2c
TL
744 (offer
745 ? (offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
746 : "BOOTREPLY"),
747 piaddr (lease -> ip_addr),
748 print_hw_addr (packet -> raw -> htype,
749 packet -> raw -> hlen,
a69f4fd3
TL
750 packet -> raw -> chaddr),
751 packet -> raw -> giaddr.s_addr
752 ? inet_ntoa (packet -> raw -> giaddr)
753 : packet -> interface -> name);
7a049f2c
TL
754
755 /* Set up the hardware address... */
756 hto.htype = packet -> raw -> htype;
757 hto.hlen = packet -> raw -> hlen;
758 memcpy (hto.haddr, packet -> raw -> chaddr, hto.hlen);
759
760 to.sin_family = AF_INET;
761#ifdef HAVE_SA_LEN
762 to.sin_len = sizeof to;
763#endif
764 memset (to.sin_zero, 0, sizeof to.sin_zero);
765
766#ifdef DEBUG_PACKET
767 dump_packet (packet);
768 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
769 dump_packet (&outgoing);
770 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
771#endif
772
ed8bcd8f 773 /* If this was gatewayed, send it back to the gateway... */
b88e8e15 774 if (raw.giaddr.s_addr) {
ed8bcd8f 775 to.sin_addr = raw.giaddr;
b88e8e15 776 to.sin_port = server_port;
8ec97099
TL
777
778 if (outgoing.packet_length < BOOTP_MIN_LEN)
779 outgoing.packet_length = BOOTP_MIN_LEN;
780
7a049f2c
TL
781#ifdef USE_FALLBACK
782 result = send_fallback (&fallback_interface,
783 packet, &raw, outgoing.packet_length,
784 raw.siaddr, &to, &hto);
785 if (result < 0)
786 warn ("send_fallback: %m");
787 return;
788#endif
b88e8e15 789
1a4b272f
TL
790 /* If it comes from a client who already knows its address and
791 is not requesting a broadcast response, sent it directly to
792 that client. */
793 } else if (raw.ciaddr.s_addr && offer == DHCPACK &&
794 !(raw.flags & BOOTP_BROADCAST)) {
ed8bcd8f 795 to.sin_addr = packet -> raw -> ciaddr;
b88e8e15
TL
796 to.sin_port = htons (ntohs (server_port) + 1); /* XXX */
797
e2cb6d53
TL
798#ifdef USE_FALLBACK
799 result = send_fallback (&fallback_interface,
800 packet, &raw, outgoing.packet_length,
801 raw.siaddr, &to, &hto);
802 if (result < 0)
803 warn ("send_fallback: %m");
804 return;
805#endif
806
ed8bcd8f 807 /* Otherwise, broadcast it on the local network. */
b88e8e15 808 } else {
fde927d2 809 to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
b88e8e15
TL
810 to.sin_port = htons (ntohs (server_port) + 1); /* XXX */
811 }
ed8bcd8f 812
fde927d2
TL
813
814 result = send_packet (packet -> interface,
815 packet, &raw, outgoing.packet_length,
7a049f2c 816 raw.siaddr, &to, &hto);
685963dc 817 if (result < 0)
a8b53b42 818 warn ("sendpkt: %m");
d7837182 819}
ed8bcd8f 820
15c00bba 821struct lease *find_lease (packet, share)
ed8bcd8f 822 struct packet *packet;
15c00bba 823 struct shared_network *share;
ed8bcd8f 824{
7a049f2c
TL
825 struct lease *uid_lease, *ip_lease, *hw_lease;
826 struct lease *lease = (struct lease *)0;
ed8bcd8f 827 struct iaddr cip;
e29c53f6 828 struct host_decl *hp, *host = (struct host_decl *)0;
7a049f2c 829 struct lease *fixed_lease;
ed8bcd8f 830
7a049f2c
TL
831 /* Try to find a host or lease that's been assigned to the
832 specified unique client identifier. */
833 if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) {
834 /* First, try to find a fixed host entry for the specified
835 client identifier... */
836 hp = find_hosts_by_uid (packet -> options
837 [DHO_DHCP_CLIENT_IDENTIFIER].data,
838 packet -> options
839 [DHO_DHCP_CLIENT_IDENTIFIER].len);
840 if (hp) {
841 host = hp;
15c00bba 842 fixed_lease = mockup_lease (packet, share, hp);
b6b1cadf 843 uid_lease = (struct lease *)0;
45023390 844 } else {
7a049f2c
TL
845 uid_lease = find_lease_by_uid
846 (packet -> options
847 [DHO_DHCP_CLIENT_IDENTIFIER].data,
848 packet -> options
849 [DHO_DHCP_CLIENT_IDENTIFIER].len);
45023390
TL
850 fixed_lease = (struct lease *)0;
851 }
7a049f2c 852 } else {
ed8bcd8f 853 uid_lease = (struct lease *)0;
7a049f2c
TL
854 fixed_lease = (struct lease *)0;
855 }
856
857 /* If we didn't find a fixed lease using the uid, try doing
858 it with the hardware address... */
859 if (!fixed_lease) {
860 hp = find_hosts_by_haddr (packet -> raw -> htype,
861 packet -> raw -> chaddr,
862 packet -> raw -> hlen);
863 if (hp) {
864 host = hp; /* Save it for later. */
15c00bba 865 fixed_lease = mockup_lease (packet, share, hp);
7a049f2c
TL
866 }
867 }
ed8bcd8f
TL
868
869 /* Try to find a lease that's been attached to the client's
870 hardware address... */
871 hw_lease = find_lease_by_hw_addr (packet -> raw -> chaddr,
872 packet -> raw -> hlen);
873
874 /* Try to find a lease that's been allocated to the client's
875 IP address. */
876 if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len &&
877 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len
878 <= sizeof cip.iabuf) {
879 cip.len = packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len;
880 memcpy (cip.iabuf,
881 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data,
882 packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len);
b6b1cadf
TL
883 ip_lease = find_lease_by_ip_addr (cip);
884 } else if (packet -> raw -> ciaddr.s_addr) {
885 cip.len = packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len;
ed8bcd8f
TL
886 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
887 ip_lease = find_lease_by_ip_addr (cip);
888 } else
889 ip_lease = (struct lease *)0;
890
f8cd781e
TL
891 /* Toss ip_lease if it hasn't yet expired and the uid doesn't
892 match */
893 if (ip_lease &&
894 ip_lease -> ends >= cur_time &&
895 ip_lease -> uid && ip_lease != uid_lease)
896 ip_lease = (struct lease *)0;
897
898 /* Toss hw_lease if it hasn't yet expired and the uid doesn't
899 match, except that if the hardware address matches and the
900 client is now doing dynamic BOOTP (and thus hasn't provided
901 a uid) we let the client get away with it. */
902 if (hw_lease &&
903 hw_lease -> ends >= cur_time &&
904 hw_lease -> uid && hw_lease != uid_lease &&
905 (packet -> packet_type != 0 ||
906 !(lease -> flags & DYNAMIC_BOOTP_OK)))
907 hw_lease = (struct lease *)0;
908
ed8bcd8f
TL
909 /* Toss extra pointers to the same lease... */
910 if (ip_lease == hw_lease)
911 ip_lease = (struct lease *)0;
912 if (hw_lease == uid_lease)
913 hw_lease = (struct lease *)0;
914 if (ip_lease == uid_lease)
915 ip_lease = (struct lease *)0;
916
917 /* If we got an ip address lease, make sure it isn't assigned to
918 some *other* client! If it was assigned to this client, we'd
919 have zeroed it out above, so the only way we can take it at this
920 point is if some other client had it but it's timed out, or if no
921 other client has ever had it. */
922 if (ip_lease &&
923 ip_lease -> ends >= cur_time)
924 ip_lease = (struct lease *)0;
925
b88e8e15
TL
926 /* If we've already eliminated the lease, it wasn't there to
927 begin with. If we have come up with a matching lease,
928 set the message to bad network in case we have to throw it out. */
929 if (!ip_lease && !hw_lease && !uid_lease) {
930 strcpy (dhcp_message, "requested address not available");
931 } else {
932 strcpy (dhcp_message, "requested address on bad subnet");
933 }
934
7a049f2c
TL
935 /* Now eliminate leases that are on the wrong network... */
936 if (ip_lease &&
15c00bba 937 (share != ip_lease -> shared_network)) {
ed8bcd8f
TL
938 release_lease (ip_lease);
939 ip_lease = (struct lease *)0;
940 }
7a049f2c 941 if (uid_lease &&
15c00bba 942 (share != uid_lease -> shared_network)) {
ed8bcd8f
TL
943 release_lease (uid_lease);
944 uid_lease = (struct lease *)0;
945 }
7a049f2c 946 if (hw_lease &&
15c00bba 947 (share != hw_lease -> shared_network)) {
ed8bcd8f
TL
948 release_lease (hw_lease);
949 hw_lease = (struct lease *)0;
950 }
951
7a049f2c 952 /* At this point, if fixed_lease is nonzero, we can assign it to
ed8bcd8f 953 this client. */
7a049f2c
TL
954 if (fixed_lease)
955 lease = fixed_lease;
956
957 /* If we got a lease that matched the ip address and don't have
958 a better offer, use that; otherwise, release it. */
959 if (ip_lease) {
960 if (lease) {
961 release_lease (ip_lease);
962 } else {
963 lease = ip_lease;
964 lease -> host = (struct host_decl *)0;
965 }
966 }
ed8bcd8f
TL
967
968 /* If we got a lease that matched the client identifier, we may want
969 to use it, but if we already have a lease we like, we must free
970 the lease that matched the client identifier. */
971 if (uid_lease) {
972 if (lease) {
973 release_lease (uid_lease);
7a049f2c 974 } else {
ed8bcd8f 975 lease = uid_lease;
7a049f2c
TL
976 lease -> host = (struct host_decl *)0;
977 }
ed8bcd8f
TL
978 }
979
980 /* The lease that matched the hardware address is treated likewise. */
981 if (hw_lease) {
982 if (lease) {
983 release_lease (hw_lease);
7a049f2c 984 } else {
ed8bcd8f 985 lease = hw_lease;
7a049f2c
TL
986 lease -> host = (struct host_decl *)0;
987 }
988 }
989
990 /* If we found a host_decl but no matching address, try to
991 find a host_decl that has no address, and if there is one,
992 hang it off the lease so that we can use the supplied
993 options. */
994 if (lease && host && !lease -> host) {
995 for (; host; host = host -> n_ipaddr) {
996 if (!host -> fixed_addr) {
997 lease -> host = host;
998 break;
999 }
1000 }
ed8bcd8f
TL
1001 }
1002
1003 return lease;
1004}
7a049f2c
TL
1005
1006/* Search the provided host_decl structure list for an address that's on
1007 the specified shared network. If one is found, mock up and return a
1008 lease structure for it; otherwise return the null pointer. */
1009
15c00bba 1010struct lease *mockup_lease (packet, share, hp)
7a049f2c 1011 struct packet *packet;
15c00bba 1012 struct shared_network *share;
7a049f2c
TL
1013 struct host_decl *hp;
1014{
1015 static struct lease mock;
1016
15c00bba 1017 mock.subnet = find_host_for_network (&hp, &mock.ip_addr, share);
7a049f2c
TL
1018 if (!mock.subnet)
1019 return (struct lease *)0;
1020 mock.next = mock.prev = (struct lease *)0;
1021 mock.shared_network = mock.subnet -> shared_network;
1022 mock.host = hp;
1023 mock.uid_len = 0;
d01578b7 1024 mock.hardware_addr = hp -> interface;
7a049f2c
TL
1025 mock.uid = (unsigned char *)0;
1026 mock.starts = mock.timestamp = mock.ends = MIN_TIME;
1027 mock.flags = STATIC_LEASE;
1028 return &mock;
1029}