ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
bootp.c
Go to the documentation of this file.
1/* bootp.c
2
3 BOOTP Protocol support. */
4
5/*
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 *
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.
20 *
21 * Internet Systems Consortium, Inc.
22 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29#include "dhcpd.h"
30#include <errno.h>
31
32#if defined (TRACING)
33# define send_packet trace_packet_send
34#endif
35
37 struct packet *packet;
38{
39 int result;
40 struct host_decl *hp = (struct host_decl *)0;
41 struct host_decl *host = (struct host_decl *)0;
42 struct packet outgoing;
43 struct dhcp_packet raw;
44 struct sockaddr_in to;
45 struct in_addr from;
46 struct hardware hto;
47 struct option_state *options = (struct option_state *)0;
48 struct lease *lease = (struct lease *)0;
49 unsigned i;
50 struct data_string d1;
51 struct option_cache *oc;
52 char msgbuf [1024];
53 int ignorep;
54 int peer_has_leases = 0;
55 int norelay = 0;
56
57 if (packet -> raw -> op != BOOTREQUEST)
58 return;
59
60 /* %Audit% This is log output. %2004.06.17,Safe%
61 * If we truncate we hope the user can get a hint from the log.
62 */
63 snprintf (msgbuf, sizeof msgbuf, "BOOTREQUEST from %s via %s",
64 print_hw_addr (packet -> raw -> htype,
65 packet -> raw -> hlen,
66 packet -> raw -> chaddr),
67 packet -> raw -> giaddr.s_addr
68 ? inet_ntoa (packet -> raw -> giaddr)
69 : packet -> interface -> name);
70
71 if ((norelay = locate_network (packet)) == 0) {
72 log_info ("%s: network unknown", msgbuf);
73 return;
74 }
75
77 0, 0, (struct lease *)0, MDL);
78
79 if (lease && lease->host)
80 host_reference(&hp, lease->host, MDL);
81
82 if (!lease || ((lease->flags & STATIC_LEASE) == 0)) {
83 struct host_decl *h;
84
85 /* We didn't find an applicable fixed-address host
86 declaration. Just in case we may be able to dynamically
87 assign an address, see if there's a host declaration
88 that doesn't have an ip address associated with it. */
89
90 if (!hp)
93 packet->raw->hlen, MDL);
94
95 for (h = hp; h; h = h -> n_ipaddr) {
96 if (!h -> fixed_addr) {
97 host_reference(&host, h, MDL);
98 break;
99 }
100 }
101
102 if (hp)
103 host_dereference(&hp, MDL);
104
105 if (host) {
106 host_reference(&hp, host, MDL);
107 host_dereference(&host, MDL);
108 }
109
110 /* Allocate a lease if we have not yet found one. */
111 if (!lease)
114 &peer_has_leases);
115
116 if (lease == NULL) {
117 log_info("%s: BOOTP from dynamic client and no "
118 "dynamic leases", msgbuf);
119 goto out;
120 }
121
122#if defined(FAILOVER_PROTOCOL)
123 if ((lease->pool != NULL) &&
124 (lease->pool->failover_peer != NULL)) {
125 dhcp_failover_state_t *peer;
126
127 peer = lease->pool->failover_peer;
128
129 /* If we are in a failover state that bars us from
130 * answering, do not do so.
131 * If we are in a cooperative state, load balance
132 * (all) responses.
133 */
134 if ((peer->service_state == not_responding) ||
135 (peer->service_state == service_startup)) {
136 log_info("%s: not responding%s",
137 msgbuf, peer->nrr);
138 goto out;
139 } else if((peer->service_state == cooperating) &&
140 !load_balance_mine(packet, peer)) {
141 log_info("%s: load balance to peer %s",
142 msgbuf, peer->name);
143 goto out;
144 }
145 }
146#endif
147
148 ack_lease (packet, lease, 0, 0, msgbuf, 0, hp);
149 goto out;
150 }
151
152 /* Run the executable statements to compute the client and server
153 options. */
154 option_state_allocate (&options, MDL);
155
156 /* Execute the subnet statements. */
158 packet->options, options,
160 NULL, NULL);
161
162 /* Execute statements from class scopes. */
163 for (i = packet -> class_count; i > 0; i--) {
165 packet->options, options,
166 &lease->scope,
167 packet->classes[i - 1]->group,
168 lease->subnet->group, NULL);
169 }
170
171 /* Execute the host statements. */
172 if (hp != NULL) {
174 packet->options, options,
175 &lease->scope, hp->group,
176 lease->subnet->group, NULL);
177 }
178
179 /* Drop the request if it's not allowed for this client. */
180 if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
182 NULL,
183 packet->options, options,
184 &lease->scope, oc, MDL)) {
185 if (!ignorep)
186 log_info ("%s: bootp disallowed", msgbuf);
187 goto out;
188 }
189
191 options, SV_ALLOW_BOOTING)) &&
193 NULL,
194 packet->options, options,
195 &lease->scope, oc, MDL)) {
196 if (!ignorep)
197 log_info ("%s: booting disallowed", msgbuf);
198 goto out;
199 }
200
201 /* Set up the outgoing packet... */
202 memset (&outgoing, 0, sizeof outgoing);
203 memset (&raw, 0, sizeof raw);
204 outgoing.raw = &raw;
205
206 /* If we didn't get a known vendor magic number on the way in,
207 just copy the input options to the output. */
209 if (!packet->options_valid &&
210 !(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
211 packet->options, options,
212 &lease->scope,
214 options, i), MDL))) {
216 memcpy(outgoing.raw->options, packet->raw->options,
218 }
219
220 outgoing.packet_length =
224 } else {
225
226 /* Use the subnet mask from the subnet declaration if no other
227 mask has been provided. */
228 oc = (struct option_cache *)0;
229 i = DHO_SUBNET_MASK;
230 if (!lookup_option (&dhcp_universe, options, i)) {
231 if (option_cache_allocate (&oc, MDL)) {
233 (&oc -> expression,
234 lease -> subnet -> netmask.iabuf,
235 lease -> subnet -> netmask.len,
236 0, 0, MDL)) {
237 option_code_hash_lookup(&oc->option,
238 dhcp_universe.code_hash,
239 &i, 0, MDL);
241 options, oc);
242 }
244 }
245 }
246
247 /* If use-host-decl-names is enabled and there is a hostname
248 * defined in the host delcartion, send it back in hostname
249 * option */
251
252 /* Pack the options into the buffer. Unlike DHCP, we
253 can't pack options into the filename and server
254 name buffers. */
255
256 outgoing.packet_length =
257 cons_options (packet, outgoing.raw, lease,
258 (struct client_state *)0, 0,
259 packet -> options, options,
260 &lease -> scope,
261 0, 0, 1, (struct data_string *)0,
262 (const char *)0);
263 if (outgoing.packet_length < BOOTP_MIN_LEN)
264 outgoing.packet_length = BOOTP_MIN_LEN;
265 }
266
267 /* Take the fields that we care about... */
268 raw.op = BOOTREPLY;
269 raw.htype = packet -> raw -> htype;
270 raw.hlen = packet -> raw -> hlen;
271 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
272 raw.hops = packet -> raw -> hops;
273 raw.xid = packet -> raw -> xid;
274 raw.secs = packet -> raw -> secs;
275 raw.flags = packet -> raw -> flags;
276 raw.ciaddr = packet -> raw -> ciaddr;
277
278 /* yiaddr is an ipv4 address, it must be 4 octets. */
279 memcpy (&raw.yiaddr, lease->ip_addr.iabuf, 4);
280
281 /* If we're always supposed to broadcast to this client, set
282 the broadcast bit in the bootp flags field. */
283 if ((oc = lookup_option (&server_universe,
284 options, SV_ALWAYS_BROADCAST)) &&
286 (struct client_state *)0,
287 packet -> options, options,
288 &lease -> scope, oc, MDL))
289 raw.flags |= htons (BOOTP_BROADCAST);
290
291 /* Figure out the address of the next server. */
292 memset (&d1, 0, sizeof d1);
294 if (oc &&
296 (struct client_state *)0,
297 packet -> options, options,
298 &lease -> scope, oc, MDL)) {
299 /* If there was more than one answer, take the first. */
300 if (d1.len >= 4 && d1.data)
301 memcpy (&raw.siaddr, d1.data, 4);
302 data_string_forget (&d1, MDL);
303 } else {
304 if ((lease->subnet->shared_network->interface != NULL) &&
306 raw.siaddr =
308 else if (packet->interface->address_count)
309 raw.siaddr = packet->interface->addresses[0];
310 }
311
312 raw.giaddr = packet -> raw -> giaddr;
313
314 /* Figure out the filename. */
315 oc = lookup_option (&server_universe, options, SV_FILENAME);
316 if (oc &&
318 (struct client_state *)0,
319 packet -> options, options,
320 &lease -> scope, oc, MDL)) {
321 memcpy (raw.file, d1.data,
322 d1.len > sizeof raw.file ? sizeof raw.file : d1.len);
323 if (sizeof raw.file > d1.len)
324 memset (&raw.file [d1.len],
325 0, (sizeof raw.file) - d1.len);
326 data_string_forget (&d1, MDL);
327 } else
328 memcpy (raw.file, packet -> raw -> file, sizeof raw.file);
329
330 /* Choose a server name as above. */
332 if (oc &&
334 (struct client_state *)0,
335 packet -> options, options,
336 &lease -> scope, oc, MDL)) {
337 memcpy (raw.sname, d1.data,
338 d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len);
339 if (sizeof raw.sname > d1.len)
340 memset (&raw.sname [d1.len],
341 0, (sizeof raw.sname) - d1.len);
342 data_string_forget (&d1, MDL);
343 }
344
345 /* Execute the commit statements, if there are any. */
347 options, &lease->scope, lease->on_star.on_commit,
348 NULL);
349
350 /* We're done with the option state. */
351 option_state_dereference (&options, MDL);
352
353#if defined(DHCPv6) && defined(DHCP4o6)
354 if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
355 /* Report what we're doing... */
356 log_info("%s", msgbuf);
357 log_info("DHCP4o6 BOOTREPLY for %s to %s (%s) via %s",
359 ((hp != NULL) && (hp->name != NULL)) ?
360 hp -> name : "unknown",
362 packet->raw->hlen,
363 packet->raw->chaddr),
365
366 /* fill dhcp4o6_response */
370 outgoing.packet_length, MDL)) {
371 log_fatal("No memory to store DHCP4o6 reply.");
372 }
376 outgoing.raw, outgoing.packet_length);
377 goto out;
378 }
379#endif
380
381 /* Set up the hardware destination address... */
382 hto.hbuf [0] = packet -> raw -> htype;
383 hto.hlen = packet -> raw -> hlen + 1;
384 memcpy (&hto.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
385
387 from = packet->interface->addresses[0];
388 } else {
389 log_error("%s: Interface %s appears to have no IPv4 "
390 "addresses, and so dhcpd cannot select a source "
391 "address.", msgbuf, packet->interface->name);
392 goto out;
393 }
394
395 /* Report what we're doing... */
396 log_info("%s", msgbuf);
397 log_info("BOOTREPLY for %s to %s (%s) via %s",
399 ((hp != NULL) && (hp->name != NULL)) ? hp -> name : "unknown",
401 packet->raw->hlen,
402 packet->raw->chaddr),
403 packet->raw->giaddr.s_addr
404 ? inet_ntoa (packet->raw->giaddr)
405 : packet->interface->name);
406
407 /* Set up the parts of the address that are in common. */
408 to.sin_family = AF_INET;
409#ifdef HAVE_SA_LEN
410 to.sin_len = sizeof to;
411#endif
412 memset (to.sin_zero, 0, sizeof to.sin_zero);
413
414 /* If this was gatewayed, send it back to the gateway... */
415 if (raw.giaddr.s_addr) {
416 to.sin_addr = raw.giaddr;
417 to.sin_port = local_port;
418
419 if (fallback_interface) {
420 result = send_packet (fallback_interface, NULL, &raw,
421 outgoing.packet_length, from,
422 &to, &hto);
423 if (result < 0) {
424 log_error ("%s:%d: Failed to send %d byte long "
425 "packet over %s interface.", MDL,
426 outgoing.packet_length,
427 fallback_interface->name);
428 }
429
430 goto out;
431 }
432 } else if (norelay == 2) {
433 to.sin_addr = raw.ciaddr;
434 to.sin_port = remote_port;
435 if (fallback_interface) {
436 result = send_packet (fallback_interface, NULL, &raw,
437 outgoing.packet_length, from,
438 &to, &hto);
439 goto out;
440 }
441
442 /* If it comes from a client that already knows its address
443 and is not requesting a broadcast response, and we can
444 unicast to a client without using the ARP protocol, sent it
445 directly to that client. */
446 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
447 can_unicast_without_arp (packet -> interface)) {
448 to.sin_addr = raw.yiaddr;
449 to.sin_port = remote_port;
450
451 /* Otherwise, broadcast it on the local network. */
452 } else {
453 to.sin_addr = limited_broadcast;
454 to.sin_port = remote_port; /* XXX */
455 }
456
457 errno = 0;
458 result = send_packet(packet->interface, packet, &raw,
459 outgoing.packet_length, from, &to, &hto);
460 if (result < 0) {
461 log_error ("%s:%d: Failed to send %d byte long packet over %s"
462 " interface.", MDL, outgoing.packet_length,
464 }
465
466 out:
467
468 if (options)
469 option_state_dereference (&options, MDL);
470 if (lease)
471 lease_dereference (&lease, MDL);
472 if (hp)
473 host_dereference (&hp, MDL);
474 if (host)
475 host_dereference (&host, MDL);
476}
void bootp(struct packet *packet)
Definition bootp.c:36
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition alloc.c:679
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition alloc.c:846
int option_state_dereference(struct option_state **ptr, const char *file, int line)
Definition alloc.c:911
int option_cache_allocate(struct option_cache **cptr, const char *file, int line)
Definition alloc.c:630
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition options.c:2818
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition options.c:2953
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2503
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, struct lease *lease, struct client_state *client_state, int mms, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, int overload_avail, int terminate, int bootpp, struct data_string *prl, const char *vuname)
Definition options.c:538
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition print.c:171
u_int16_t remote_port
Definition discover.c:49
struct in_addr giaddr
Definition dhclient.c:77
u_int16_t local_port
Definition discover.c:48
#define BOOTP_MIN_LEN
Definition dhcp.h:39
#define BOOTREPLY
Definition dhcp.h:69
#define DHCP_FIXED_NON_UDP
Definition dhcp.h:36
#define BOOTREQUEST
Definition dhcp.h:68
#define BOOTP_BROADCAST
Definition dhcp.h:72
#define DHO_SUBNET_MASK
Definition dhcp.h:90
#define SV_ALWAYS_REPLY_RFC1048
Definition dhcpd.h:730
#define SV_SERVER_NAME
Definition dhcpd.h:726
void use_host_decl_name(struct packet *, struct lease *, struct option_state *)
Adds hostname option when use-host-decl-names is enabled.
Definition dhcp.c:5732
int find_hosts_by_haddr(struct host_decl **, int, const unsigned char *, unsigned, const char *, int)
Definition mdb.c:632
#define SV_NEXT_SERVER
Definition dhcpd.h:727
struct ipv6_pool ** pools
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
#define SV_ALLOW_BOOTING
Definition dhcpd.h:719
#define STATIC_LEASE
Definition dhcpd.h:592
int allocate_lease(struct lease **, struct packet *, struct pool *, int *)
Definition dhcp.c:5019
struct universe server_universe
Definition stables.c:176
#define SV_FILENAME
Definition dhcpd.h:725
struct universe dhcp_universe
#define SV_ALLOW_BOOTP
Definition dhcpd.h:718
void ack_lease(struct packet *, struct lease *, unsigned int, TIME, char *, int, struct host_decl *)
Definition dhcp.c:2201
int can_unicast_without_arp(struct interface_info *)
int locate_network(struct packet *)
Definition dhcp.c:5363
int find_lease(struct lease **, struct packet *, struct shared_network *, int *, int *, struct lease *, const char *, int)
Definition dhcp.c:4213
int load_balance_mine(struct packet *, dhcp_failover_state_t *)
const char * file
Definition dhcpd.h:3802
#define SV_ALWAYS_BROADCAST
Definition dhcpd.h:732
struct interface_info * fallback_interface
Definition discover.c:44
struct in_addr limited_broadcast
Definition discover.c:57
int dhcpv4_over_dhcpv6
Definition discover.c:51
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
Definition execute.c:35
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
Definition execute.c:570
@ service_startup
Definition failover.h:321
@ cooperating
Definition failover.h:317
@ not_responding
Definition failover.h:320
const char * piaddr(const struct iaddr addr)
Definition inet.c:579
#define MDL
Definition omapip.h:567
int log_error(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
unsigned char data[1]
Definition tree.h:62
struct group * group
Definition dhcpd.h:1129
struct buffer * buffer
Definition tree.h:77
const unsigned char * data
Definition tree.h:78
unsigned len
Definition tree.h:79
struct in_addr siaddr
Definition dhcp.h:57
u_int16_t flags
Definition dhcp.h:54
u_int32_t xid
Definition dhcp.h:52
struct in_addr ciaddr
Definition dhcp.h:55
char file[DHCP_FILE_LEN]
Definition dhcp.h:61
unsigned char options[DHCP_MAX_OPTION_LEN]
Definition dhcp.h:62
u_int8_t op
Definition dhcp.h:48
struct in_addr giaddr
Definition dhcp.h:58
u_int8_t htype
Definition dhcp.h:49
struct in_addr yiaddr
Definition dhcp.h:56
u_int16_t secs
Definition dhcp.h:53
u_int8_t hlen
Definition dhcp.h:50
unsigned char chaddr[16]
Definition dhcp.h:59
char sname[DHCP_SNAME_LEN]
Definition dhcp.h:60
u_int8_t hops
Definition dhcp.h:51
u_int8_t hlen
Definition dhcpd.h:492
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition dhcpd.h:493
char * name
Definition dhcpd.h:978
struct option_cache * fixed_addr
Definition dhcpd.h:986
struct group * group
Definition dhcpd.h:988
struct host_decl * n_ipaddr
Definition dhcpd.h:976
unsigned char iabuf[16]
Definition inet.h:33
char name[IFNAMSIZ]
Definition dhcpd.h:1408
int address_count
Definition dhcpd.h:1391
struct in_addr * addresses
Definition dhcpd.h:1388
Definition dhcpd.h:560
struct pool * pool
Definition dhcpd.h:578
u_int8_t flags
Definition dhcpd.h:591
struct binding_scope * scope
Definition dhcpd.h:575
struct iaddr ip_addr
Definition dhcpd.h:569
struct on_star on_star
Definition dhcpd.h:583
struct subnet * subnet
Definition dhcpd.h:577
struct host_decl * host
Definition dhcpd.h:576
struct executable_statement * on_commit
Definition dhcpd.h:555
struct option * option
Definition dhcpd.h:389
u_int32_t flags
Definition dhcpd.h:393
struct dhcp_packet * raw
Definition dhcpd.h:406
struct interface_info * interface
Definition dhcpd.h:433
struct option_state * options
Definition dhcpd.h:449
unsigned packet_length
Definition dhcpd.h:408
struct data_string * dhcp4o6_response
Definition dhcpd.h:428
int options_valid
Definition dhcpd.h:430
struct class * classes[PACKET_MAX_CLASSES]
Definition dhcpd.h:455
struct iaddr client_addr
Definition dhcpd.h:432
dhcp_failover_state_t * failover_peer
Definition dhcpd.h:1051
struct interface_info * interface
Definition dhcpd.h:1066
struct group * group
Definition dhcpd.h:1085
struct shared_network * shared_network
Definition dhcpd.h:1079
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2699
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2733
int make_const_data(struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line)
Definition tree.c:219