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