]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/bootp.c
[master] Add abandon-lease-time parameter
[thirdparty/dhcp.git] / server / bootp.c
CommitLineData
d7837182
TL
1/* bootp.c
2
3 BOOTP Protocol support. */
4
5/*
9deef2e7 6 * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1995-2003 by Internet Software Consortium
d7837182 8 *
98311e4b
DH
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
d7837182 12 *
98311e4b
DH
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d7837182 20 *
98311e4b
DH
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
d7837182
TL
27 */
28
d7837182 29#include "dhcpd.h"
fe5b0fdd 30#include <errno.h>
d7837182 31
93016999
TL
32#if defined (TRACING)
33# define send_packet trace_packet_send
34#endif
35
d7837182
TL
36void bootp (packet)
37 struct packet *packet;
38{
39 int result;
20916cae 40 struct host_decl *hp = (struct host_decl *)0;
cfb326fd 41 struct host_decl *host = (struct host_decl *)0;
9c238be6
TL
42 struct packet outgoing;
43 struct dhcp_packet raw;
d7837182 44 struct sockaddr_in to;
d1c53034 45 struct in_addr from;
fde927d2 46 struct hardware hto;
7e6f3635 47 struct option_state *options = (struct option_state *)0;
c75473d8 48 struct lease *lease = (struct lease *)0;
b1b7b521 49 unsigned i;
ef0afca9 50 struct data_string d1;
5d25508c 51 struct option_cache *oc;
cc70b445 52 char msgbuf [1024];
e13ff8b2 53 int ignorep;
ac3ecc7f 54 int peer_has_leases = 0;
d7837182 55
c0257f22
TL
56 if (packet -> raw -> op != BOOTREQUEST)
57 return;
58
98311e4b
DH
59 /* %Audit% This is log output. %2004.06.17,Safe%
60 * If we truncate we hope the user can get a hint from the log.
61 */
62 snprintf (msgbuf, sizeof msgbuf, "BOOTREQUEST from %s via %s",
cc70b445
TL
63 print_hw_addr (packet -> raw -> htype,
64 packet -> raw -> hlen,
65 packet -> raw -> chaddr),
66 packet -> raw -> giaddr.s_addr
67 ? inet_ntoa (packet -> raw -> giaddr)
68 : packet -> interface -> name);
b837c98f 69
cc70b445 70 if (!locate_network (packet)) {
8ae2d595 71 log_info ("%s: network unknown", msgbuf);
d1c53034 72 return;
cc70b445 73 }
3a581108 74
9e383163
TL
75 find_lease (&lease, packet, packet -> shared_network,
76 0, 0, (struct lease *)0, MDL);
cfb326fd 77
c75473d8
DH
78 if (lease && lease->host)
79 host_reference(&hp, lease->host, MDL);
cfb326fd 80
c75473d8 81 if (!lease || ((lease->flags & STATIC_LEASE) == 0)) {
20916cae 82 struct host_decl *h;
c104546d 83
c75473d8
DH
84 /* We didn't find an applicable fixed-address host
85 declaration. Just in case we may be able to dynamically
86 assign an address, see if there's a host declaration
cfb326fd 87 that doesn't have an ip address associated with it. */
c75473d8
DH
88
89 if (!hp)
90 find_hosts_by_haddr(&hp, packet->raw->htype,
91 packet->raw->chaddr,
92 packet->raw->hlen, MDL);
93
20916cae
TL
94 for (h = hp; h; h = h -> n_ipaddr) {
95 if (!h -> fixed_addr) {
c75473d8 96 host_reference(&host, h, MDL);
20916cae 97 break;
cfb326fd
TL
98 }
99 }
cfb326fd 100
c75473d8
DH
101 if (hp)
102 host_dereference(&hp, MDL);
103
104 if (host) {
105 host_reference(&hp, host, MDL);
106 host_dereference(&host, MDL);
cfb326fd 107 }
98311e4b 108
c75473d8
DH
109 /* Allocate a lease if we have not yet found one. */
110 if (!lease)
111 allocate_lease (&lease, packet,
112 packet -> shared_network -> pools,
113 &peer_has_leases);
114
c104546d
DH
115 if (lease == NULL) {
116 log_info("%s: BOOTP from dynamic client and no "
117 "dynamic leases", msgbuf);
118 goto out;
119 }
120
121#if defined(FAILOVER_PROTOCOL)
122 if ((lease->pool != NULL) &&
123 (lease->pool->failover_peer != NULL)) {
124 dhcp_failover_state_t *peer;
125
126 peer = lease->pool->failover_peer;
127
128 /* If we are in a failover state that bars us from
129 * answering, do not do so.
130 * If we are in a cooperative state, load balance
131 * (all) responses.
132 */
133 if ((peer->service_state == not_responding) ||
134 (peer->service_state == service_startup)) {
135 log_info("%s: not responding%s",
136 msgbuf, peer->nrr);
137 goto out;
138 } else if((peer->service_state == cooperating) &&
139 !load_balance_mine(packet, peer)) {
140 log_info("%s: load balance to peer %s",
141 msgbuf, peer->name);
142 goto out;
143 }
144 }
145#endif
c75473d8 146
c104546d 147 ack_lease (packet, lease, 0, 0, msgbuf, 0, hp);
20916cae 148 goto out;
d7837182 149 }
9c238be6 150
ef0afca9
TL
151 /* Run the executable statements to compute the client and server
152 options. */
12c9957e 153 option_state_allocate (&options, MDL);
c75473d8 154
ef0afca9 155 /* Execute the subnet statements. */
a7341359
SR
156 execute_statements_in_scope (NULL, packet, lease, NULL,
157 packet->options, options,
158 &lease->scope, lease->subnet->group,
159 NULL, NULL);
c75473d8 160
fa661adb
TL
161 /* Execute statements from class scopes. */
162 for (i = packet -> class_count; i > 0; i--) {
a7341359
SR
163 execute_statements_in_scope(NULL, packet, lease, NULL,
164 packet->options, options,
165 &lease->scope,
166 packet->classes[i - 1]->group,
167 lease->subnet->group, NULL);
fa661adb
TL
168 }
169
ef0afca9 170 /* Execute the host statements. */
d289ee68 171 if (hp != NULL) {
0a7e1a8a
TM
172 execute_statements_in_scope(NULL, packet, lease, NULL,
173 packet->options, options,
174 &lease->scope, hp->group,
175 lease->subnet->group, NULL);
d289ee68 176 }
ef0afca9
TL
177
178 /* Drop the request if it's not allowed for this client. */
fe849040 179 if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
0a7e1a8a
TM
180 !evaluate_boolean_option_cache(&ignorep, packet, lease,
181 NULL,
182 packet->options, options,
183 &lease->scope, oc, MDL)) {
e13ff8b2
TL
184 if (!ignorep)
185 log_info ("%s: bootp disallowed", msgbuf);
20916cae 186 goto out;
ef0afca9
TL
187 }
188
0a7e1a8a 189 if ((oc = lookup_option(&server_universe,
fe849040 190 options, SV_ALLOW_BOOTING)) &&
0a7e1a8a
TM
191 !evaluate_boolean_option_cache(&ignorep, packet, lease,
192 NULL,
193 packet->options, options,
194 &lease->scope, oc, MDL)) {
e13ff8b2
TL
195 if (!ignorep)
196 log_info ("%s: booting disallowed", msgbuf);
20916cae 197 goto out;
e07ac89a 198 }
ef0afca9 199
9c238be6
TL
200 /* Set up the outgoing packet... */
201 memset (&outgoing, 0, sizeof outgoing);
202 memset (&raw, 0, sizeof raw);
203 outgoing.raw = &raw;
204
d8ae14c6
TL
205 /* If we didn't get a known vendor magic number on the way in,
206 just copy the input options to the output. */
0a7e1a8a
TM
207 i = SV_ALWAYS_REPLY_RFC1048;
208 if (!packet->options_valid &&
209 !(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
210 packet->options, options,
211 &lease->scope,
212 lookup_option (&server_universe,
213 options, i), MDL))) {
214 if (packet->packet_length > DHCP_FIXED_NON_UDP) {
215 memcpy(outgoing.raw->options, packet->raw->options,
216 packet->packet_length - DHCP_FIXED_NON_UDP);
217 }
218
219 outgoing.packet_length =
220 (packet->packet_length < BOOTP_MIN_LEN)
221 ? BOOTP_MIN_LEN
222 : packet->packet_length;
d8ae14c6 223 } else {
9804a56a
TL
224
225 /* Use the subnet mask from the subnet declaration if no other
226 mask has been provided. */
9804a56a
TL
227 oc = (struct option_cache *)0;
228 i = DHO_SUBNET_MASK;
229 if (!lookup_option (&dhcp_universe, options, i)) {
12c9957e 230 if (option_cache_allocate (&oc, MDL)) {
9804a56a
TL
231 if (make_const_data
232 (&oc -> expression,
233 lease -> subnet -> netmask.iabuf,
d758ad8c
TL
234 lease -> subnet -> netmask.len,
235 0, 0, MDL)) {
f7fdb216
DH
236 option_code_hash_lookup(&oc->option,
237 dhcp_universe.code_hash,
238 &i, 0, MDL);
9804a56a
TL
239 save_option (&dhcp_universe,
240 options, oc);
241 }
12c9957e 242 option_cache_dereference (&oc, MDL);
9804a56a
TL
243 }
244 }
245
0a7e1a8a
TM
246 /* If use-host-decl-names is enabled and there is a hostname
247 * defined in the host delcartion, send it back in hostname
248 * option */
249 use_host_decl_name(packet, lease, options);
250
d8ae14c6
TL
251 /* Pack the options into the buffer. Unlike DHCP, we
252 can't pack options into the filename and server
253 name buffers. */
9c238be6 254
d8ae14c6 255 outgoing.packet_length =
9e383163
TL
256 cons_options (packet, outgoing.raw, lease,
257 (struct client_state *)0, 0,
2cc0151c 258 packet -> options, options,
12c9957e 259 &lease -> scope,
63b935b6
TL
260 0, 0, 1, (struct data_string *)0,
261 (const char *)0);
d8ae14c6
TL
262 if (outgoing.packet_length < BOOTP_MIN_LEN)
263 outgoing.packet_length = BOOTP_MIN_LEN;
264 }
9c238be6 265
d7837182 266 /* Take the fields that we care about... */
9c238be6
TL
267 raw.op = BOOTREPLY;
268 raw.htype = packet -> raw -> htype;
269 raw.hlen = packet -> raw -> hlen;
d8ae14c6 270 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
9c238be6
TL
271 raw.hops = packet -> raw -> hops;
272 raw.xid = packet -> raw -> xid;
273 raw.secs = packet -> raw -> secs;
9129caed 274 raw.flags = packet -> raw -> flags;
9c238be6 275 raw.ciaddr = packet -> raw -> ciaddr;
c75473d8
DH
276
277 /* yiaddr is an ipv4 address, it must be 4 octets. */
278 memcpy (&raw.yiaddr, lease->ip_addr.iabuf, 4);
cfb326fd 279
9129caed
TL
280 /* If we're always supposed to broadcast to this client, set
281 the broadcast bit in the bootp flags field. */
e3b5f7f8
TL
282 if ((oc = lookup_option (&server_universe,
283 options, SV_ALWAYS_BROADCAST)) &&
e13ff8b2 284 evaluate_boolean_option_cache (&ignorep, packet, lease,
9e383163 285 (struct client_state *)0,
12c9957e
TL
286 packet -> options, options,
287 &lease -> scope, oc, MDL))
9129caed
TL
288 raw.flags |= htons (BOOTP_BROADCAST);
289
d1c53034 290 /* Figure out the address of the next server. */
e40810bf 291 memset (&d1, 0, sizeof d1);
02124b3c 292 oc = lookup_option (&server_universe, options, SV_NEXT_SERVER);
5d25508c 293 if (oc &&
2cc0151c 294 evaluate_option_cache (&d1, packet, lease,
9e383163 295 (struct client_state *)0,
12c9957e
TL
296 packet -> options, options,
297 &lease -> scope, oc, MDL)) {
ef0afca9
TL
298 /* If there was more than one answer, take the first. */
299 if (d1.len >= 4 && d1.data)
300 memcpy (&raw.siaddr, d1.data, 4);
12c9957e 301 data_string_forget (&d1, MDL);
17f1bc9a 302 } else {
98bd7ca0
DH
303 if ((lease->subnet->shared_network->interface != NULL) &&
304 lease->subnet->shared_network->interface->address_count)
305 raw.siaddr =
306 lease->subnet->shared_network->interface->addresses[0];
307 else if (packet->interface->address_count)
308 raw.siaddr = packet->interface->addresses[0];
ef0afca9 309 }
cfb326fd 310
9c238be6 311 raw.giaddr = packet -> raw -> giaddr;
ef0afca9
TL
312
313 /* Figure out the filename. */
02124b3c 314 oc = lookup_option (&server_universe, options, SV_FILENAME);
5d25508c 315 if (oc &&
2cc0151c 316 evaluate_option_cache (&d1, packet, lease,
9e383163 317 (struct client_state *)0,
12c9957e
TL
318 packet -> options, options,
319 &lease -> scope, oc, MDL)) {
ef0afca9
TL
320 memcpy (raw.file, d1.data,
321 d1.len > sizeof raw.file ? sizeof raw.file : d1.len);
322 if (sizeof raw.file > d1.len)
323 memset (&raw.file [d1.len],
324 0, (sizeof raw.file) - d1.len);
12c9957e 325 data_string_forget (&d1, MDL);
339b0231 326 } else
92e3e691 327 memcpy (raw.file, packet -> raw -> file, sizeof raw.file);
ef0afca9
TL
328
329 /* Choose a server name as above. */
02124b3c 330 oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
5d25508c 331 if (oc &&
2cc0151c 332 evaluate_option_cache (&d1, packet, lease,
9e383163 333 (struct client_state *)0,
12c9957e
TL
334 packet -> options, options,
335 &lease -> scope, oc, MDL)) {
ef0afca9
TL
336 memcpy (raw.sname, d1.data,
337 d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len);
338 if (sizeof raw.sname > d1.len)
339 memset (&raw.sname [d1.len],
340 0, (sizeof raw.sname) - d1.len);
12c9957e 341 data_string_forget (&d1, MDL);
d7837182 342 }
d7837182 343
26413cf1 344 /* Execute the commit statements, if there are any. */
a7341359
SR
345 execute_statements (NULL, packet, lease, NULL, packet->options,
346 options, &lease->scope, lease->on_star.on_commit,
347 NULL);
26413cf1 348
7e6f3635 349 /* We're done with the option state. */
12c9957e 350 option_state_dereference (&options, MDL);
7e6f3635 351
785c1a51
FD
352#if defined(DHCPv6) && defined(DHCP4o6)
353 if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
354 /* Report what we're doing... */
355 log_info("%s", msgbuf);
356 log_info("DHCP4o6 BOOTREPLY for %s to %s (%s) via %s",
357 piaddr(lease->ip_addr),
358 ((hp != NULL) && (hp->name != NULL)) ?
359 hp -> name : "unknown",
360 print_hw_addr (packet->raw->htype,
361 packet->raw->hlen,
362 packet->raw->chaddr),
363 piaddr(packet->client_addr));
364
365 /* fill dhcp4o6_response */
366 packet->dhcp4o6_response->len = outgoing.packet_length;
367 packet->dhcp4o6_response->buffer = NULL;
368 if (!buffer_allocate(&packet->dhcp4o6_response->buffer,
369 outgoing.packet_length, MDL)) {
370 log_fatal("No memory to store DHCP4o6 reply.");
371 }
372 packet->dhcp4o6_response->data =
373 packet->dhcp4o6_response->buffer->data;
374 memcpy(packet->dhcp4o6_response->buffer->data,
375 outgoing.raw, outgoing.packet_length);
376 goto out;
377 }
378#endif
379
cfb326fd 380 /* Set up the hardware destination address... */
9e9b2261
TL
381 hto.hbuf [0] = packet -> raw -> htype;
382 hto.hlen = packet -> raw -> hlen + 1;
012c4143 383 memcpy (&hto.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
cfb326fd 384
dd484ced 385 if (packet->interface->address_count) {
98bd7ca0 386 from = packet->interface->addresses[0];
dd484ced
DH
387 } else {
388 log_error("%s: Interface %s appears to have no IPv4 "
389 "addresses, and so dhcpd cannot select a source "
390 "address.", msgbuf, packet->interface->name);
391 goto out;
392 }
d1c53034 393
cfb326fd 394 /* Report what we're doing... */
d289ee68
SR
395 log_info("%s", msgbuf);
396 log_info("BOOTREPLY for %s to %s (%s) via %s",
397 piaddr(lease->ip_addr),
398 ((hp != NULL) && (hp->name != NULL)) ? hp -> name : "unknown",
399 print_hw_addr (packet->raw->htype,
400 packet->raw->hlen,
401 packet->raw->chaddr),
402 packet->raw->giaddr.s_addr
403 ? inet_ntoa (packet->raw->giaddr)
404 : packet->interface->name);
cfb326fd
TL
405
406 /* Set up the parts of the address that are in common. */
407 to.sin_family = AF_INET;
408#ifdef HAVE_SA_LEN
409 to.sin_len = sizeof to;
410#endif
411 memset (to.sin_zero, 0, sizeof to.sin_zero);
412
9c238be6
TL
413 /* If this was gatewayed, send it back to the gateway... */
414 if (raw.giaddr.s_addr) {
415 to.sin_addr = raw.giaddr;
bfa885c9 416 to.sin_port = local_port;
cfb326fd 417
92e3e691 418 if (fallback_interface) {
dd9237c3
TM
419 result = send_packet (fallback_interface, NULL, &raw,
420 outgoing.packet_length, from,
421 &to, &hto);
422 if (result < 0) {
423 log_error ("%s:%d: Failed to send %d byte long "
424 "packet over %s interface.", MDL,
425 outgoing.packet_length,
426 fallback_interface->name);
427 }
428
20916cae 429 goto out;
92e3e691 430 }
fe849040
TL
431
432 /* If it comes from a client that already knows its address
433 and is not requesting a broadcast response, and we can
434 unicast to a client without using the ARP protocol, sent it
435 directly to that client. */
436 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
437 can_unicast_without_arp (packet -> interface)) {
438 to.sin_addr = raw.yiaddr;
439 to.sin_port = remote_port;
440
9c238be6
TL
441 /* Otherwise, broadcast it on the local network. */
442 } else {
71df44f5 443 to.sin_addr = limited_broadcast;
bfa885c9 444 to.sin_port = remote_port; /* XXX */
9c238be6 445 }
d7837182 446
d7837182 447 errno = 0;
dd9237c3
TM
448 result = send_packet(packet->interface, packet, &raw,
449 outgoing.packet_length, from, &to, &hto);
450 if (result < 0) {
451 log_error ("%s:%d: Failed to send %d byte long packet over %s"
452 " interface.", MDL, outgoing.packet_length,
453 packet->interface->name);
454 }
455
20916cae 456 out:
dd9237c3 457
20916cae
TL
458 if (options)
459 option_state_dereference (&options, MDL);
31bbee78 460 if (lease)
20916cae 461 lease_dereference (&lease, MDL);
20916cae
TL
462 if (hp)
463 host_dereference (&hp, MDL);
464 if (host)
465 host_dereference (&host, MDL);
d7837182 466}