ISC DHCP  4.3.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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  (struct client_state *)0,
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  (struct client_state *)0,
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. */
209  if (!packet -> options_valid &&
211  (&ignorep, packet, lease, (struct client_state *)0,
212  packet -> options, options, &lease -> scope,
213  lookup_option (&server_universe, options,
215  memcpy (outgoing.raw -> options,
216  packet -> raw -> options, DHCP_MAX_OPTION_LEN);
217  outgoing.packet_length = BOOTP_MIN_LEN;
218  } else {
219 
220  /* Use the subnet mask from the subnet declaration if no other
221  mask has been provided. */
222 
223  oc = (struct option_cache *)0;
224  i = DHO_SUBNET_MASK;
225  if (!lookup_option (&dhcp_universe, options, i)) {
226  if (option_cache_allocate (&oc, MDL)) {
227  if (make_const_data
228  (&oc -> expression,
229  lease -> subnet -> netmask.iabuf,
230  lease -> subnet -> netmask.len,
231  0, 0, MDL)) {
232  option_code_hash_lookup(&oc->option,
234  &i, 0, MDL);
236  options, oc);
237  }
239  }
240  }
241 
242  /* Pack the options into the buffer. Unlike DHCP, we
243  can't pack options into the filename and server
244  name buffers. */
245 
246  outgoing.packet_length =
247  cons_options (packet, outgoing.raw, lease,
248  (struct client_state *)0, 0,
249  packet -> options, options,
250  &lease -> scope,
251  0, 0, 1, (struct data_string *)0,
252  (const char *)0);
253  if (outgoing.packet_length < BOOTP_MIN_LEN)
254  outgoing.packet_length = BOOTP_MIN_LEN;
255  }
256 
257  /* Take the fields that we care about... */
258  raw.op = BOOTREPLY;
259  raw.htype = packet -> raw -> htype;
260  raw.hlen = packet -> raw -> hlen;
261  memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
262  raw.hops = packet -> raw -> hops;
263  raw.xid = packet -> raw -> xid;
264  raw.secs = packet -> raw -> secs;
265  raw.flags = packet -> raw -> flags;
266  raw.ciaddr = packet -> raw -> ciaddr;
267 
268  /* yiaddr is an ipv4 address, it must be 4 octets. */
269  memcpy (&raw.yiaddr, lease->ip_addr.iabuf, 4);
270 
271  /* If we're always supposed to broadcast to this client, set
272  the broadcast bit in the bootp flags field. */
273  if ((oc = lookup_option (&server_universe,
274  options, SV_ALWAYS_BROADCAST)) &&
275  evaluate_boolean_option_cache (&ignorep, packet, lease,
276  (struct client_state *)0,
277  packet -> options, options,
278  &lease -> scope, oc, MDL))
279  raw.flags |= htons (BOOTP_BROADCAST);
280 
281  /* Figure out the address of the next server. */
282  memset (&d1, 0, sizeof d1);
283  oc = lookup_option (&server_universe, options, SV_NEXT_SERVER);
284  if (oc &&
285  evaluate_option_cache (&d1, packet, lease,
286  (struct client_state *)0,
287  packet -> options, options,
288  &lease -> scope, oc, MDL)) {
289  /* If there was more than one answer, take the first. */
290  if (d1.len >= 4 && d1.data)
291  memcpy (&raw.siaddr, d1.data, 4);
292  data_string_forget (&d1, MDL);
293  } else {
294  if ((lease->subnet->shared_network->interface != NULL) &&
296  raw.siaddr =
298  else if (packet->interface->address_count)
299  raw.siaddr = packet->interface->addresses[0];
300  }
301 
302  raw.giaddr = packet -> raw -> giaddr;
303 
304  /* Figure out the filename. */
305  oc = lookup_option (&server_universe, options, SV_FILENAME);
306  if (oc &&
307  evaluate_option_cache (&d1, packet, lease,
308  (struct client_state *)0,
309  packet -> options, options,
310  &lease -> scope, oc, MDL)) {
311  memcpy (raw.file, d1.data,
312  d1.len > sizeof raw.file ? sizeof raw.file : d1.len);
313  if (sizeof raw.file > d1.len)
314  memset (&raw.file [d1.len],
315  0, (sizeof raw.file) - d1.len);
316  data_string_forget (&d1, MDL);
317  } else
318  memcpy (raw.file, packet -> raw -> file, sizeof raw.file);
319 
320  /* Choose a server name as above. */
321  oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
322  if (oc &&
323  evaluate_option_cache (&d1, packet, lease,
324  (struct client_state *)0,
325  packet -> options, options,
326  &lease -> scope, oc, MDL)) {
327  memcpy (raw.sname, d1.data,
328  d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len);
329  if (sizeof raw.sname > d1.len)
330  memset (&raw.sname [d1.len],
331  0, (sizeof raw.sname) - d1.len);
332  data_string_forget (&d1, MDL);
333  }
334 
335  /* Execute the commit statements, if there are any. */
336  execute_statements (NULL, packet, lease, NULL, packet->options,
337  options, &lease->scope, lease->on_star.on_commit,
338  NULL);
339 
340  /* We're done with the option state. */
341  option_state_dereference (&options, MDL);
342 
343  /* Set up the hardware destination address... */
344  hto.hbuf [0] = packet -> raw -> htype;
345  hto.hlen = packet -> raw -> hlen + 1;
346  memcpy (&hto.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
347 
348  if (packet->interface->address_count) {
349  from = packet->interface->addresses[0];
350  } else {
351  log_error("%s: Interface %s appears to have no IPv4 "
352  "addresses, and so dhcpd cannot select a source "
353  "address.", msgbuf, packet->interface->name);
354  goto out;
355  }
356 
357  /* Report what we're doing... */
358  log_info("%s", msgbuf);
359  log_info("BOOTREPLY for %s to %s (%s) via %s",
360  piaddr(lease->ip_addr),
361  ((hp != NULL) && (hp->name != NULL)) ? hp -> name : "unknown",
362  print_hw_addr (packet->raw->htype,
363  packet->raw->hlen,
364  packet->raw->chaddr),
365  packet->raw->giaddr.s_addr
366  ? inet_ntoa (packet->raw->giaddr)
367  : packet->interface->name);
368 
369  /* Set up the parts of the address that are in common. */
370  to.sin_family = AF_INET;
371 #ifdef HAVE_SA_LEN
372  to.sin_len = sizeof to;
373 #endif
374  memset (to.sin_zero, 0, sizeof to.sin_zero);
375 
376  /* If this was gatewayed, send it back to the gateway... */
377  if (raw.giaddr.s_addr) {
378  to.sin_addr = raw.giaddr;
379  to.sin_port = local_port;
380 
381  if (fallback_interface) {
382  result = send_packet (fallback_interface, NULL, &raw,
383  outgoing.packet_length, from,
384  &to, &hto);
385  if (result < 0) {
386  log_error ("%s:%d: Failed to send %d byte long "
387  "packet over %s interface.", MDL,
388  outgoing.packet_length,
390  }
391 
392  goto out;
393  }
394  } else if (norelay == 2) {
395  to.sin_addr = raw.ciaddr;
396  to.sin_port = remote_port;
397  if (fallback_interface) {
398  result = send_packet (fallback_interface, NULL, &raw,
399  outgoing.packet_length, from,
400  &to, &hto);
401  goto out;
402  }
403 
404  /* If it comes from a client that already knows its address
405  and is not requesting a broadcast response, and we can
406  unicast to a client without using the ARP protocol, sent it
407  directly to that client. */
408  } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
409  can_unicast_without_arp (packet -> interface)) {
410  to.sin_addr = raw.yiaddr;
411  to.sin_port = remote_port;
412 
413  /* Otherwise, broadcast it on the local network. */
414  } else {
415  to.sin_addr = limited_broadcast;
416  to.sin_port = remote_port; /* XXX */
417  }
418 
419  errno = 0;
420  result = send_packet(packet->interface, packet, &raw,
421  outgoing.packet_length, from, &to, &hto);
422  if (result < 0) {
423  log_error ("%s:%d: Failed to send %d byte long packet over %s"
424  " interface.", MDL, outgoing.packet_length,
425  packet->interface->name);
426  }
427 
428  out:
429 
430  if (options)
431  option_state_dereference (&options, MDL);
432  if (lease)
433  lease_dereference (&lease, MDL);
434  if (hp)
435  host_dereference (&hp, MDL);
436  if (host)
437  host_dereference (&host, MDL);
438 }
#define BOOTREPLY
Definition: dhcp.h:70
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:3749
char sname[DHCP_SNAME_LEN]
Definition: dhcp.h:61
u_int32_t flags
Definition: dhcpd.h:357
#define SV_ALLOW_BOOTING
Definition: dhcpd.h:655
struct on_star on_star
Definition: dhcpd.h:523
Definition: dhcpd.h:507
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition: options.c:2618
unsigned len
Definition: tree.h:80
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
u_int8_t hlen
Definition: dhcpd.h:440
char name[IFNAMSIZ]
Definition: dhcpd.h:1272
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition: options.c:2753
u_int16_t secs
Definition: dhcp.h:54
Definition: dhcpd.h:952
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:1252
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1276
struct option_cache * fixed_addr
Definition: dhcpd.h:875
#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:662
int allocate_lease(struct lease **, struct packet *, struct pool *, int *)
Definition: dhcp.c:4553
dhcp_failover_state_t * failover_peer
Definition: dhcpd.h:928
int find_hosts_by_haddr(struct host_decl **, int, const unsigned char *, unsigned, const char *, int)
Definition: mdb.c:610
#define SV_FILENAME
Definition: dhcpd.h:661
u_int16_t flags
Definition: dhcp.h:55
#define BOOTP_MIN_LEN
Definition: dhcp.h:40
#define SV_ALLOW_BOOTP
Definition: dhcpd.h:654
int locate_network(struct packet *)
Definition: dhcp.c:4769
int option_cache_allocate(struct option_cache **cptr, const char *file, int line)
Definition: alloc.c:631
struct dhcp_packet * raw
Definition: dhcpd.h:370
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:555
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:2643
unsigned char chaddr[16]
Definition: dhcp.h:60
#define SV_NEXT_SERVER
Definition: dhcpd.h:663
#define DHCP_MAX_OPTION_LEN
Definition: dhcp.h:45
u_int32_t xid
Definition: dhcp.h:53
#define SV_ALWAYS_BROADCAST
Definition: dhcpd.h:668
u_int16_t local_port
Definition: dhclient.c:88
Definition: dhcpd.h:369
struct pool * pool
Definition: dhcpd.h:518
char * name
Definition: dhcpd.h:867
#define SV_ALWAYS_REPLY_RFC1048
Definition: dhcpd.h:666
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:523
u_int8_t flags
Definition: dhcpd.h:531
struct in_addr giaddr
Definition: dhclient.c:73
struct host_decl * n_ipaddr
Definition: dhcpd.h:865
#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:2303
struct option * option
Definition: dhcpd.h:353
struct in_addr limited_broadcast
Definition: discover.c:53
int int log_info(const char *,...) __attribute__((__format__(__printf__
struct subnet * subnet
Definition: dhcpd.h:517
struct shared_network * shared_network
Definition: dhcpd.h:956
void bootp(struct packet *packet)
Definition: bootp.c:37
struct group * group
Definition: dhcpd.h:962
struct iaddr ip_addr
Definition: dhcpd.h:512
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:2670
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:516
void ack_lease(struct packet *, struct lease *, unsigned int, TIME, char *, int, struct host_decl *)
Definition: dhcp.c:1884
struct interface_info * interface
Definition: dhcpd.h:943
#define STATIC_LEASE
Definition: dhcpd.h:532
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:441
int address_count
Definition: dhcpd.h:1255
u_int8_t hops
Definition: dhcp.h:52
struct ipv6_pool ** pools
option_code_hash_t * code_hash
Definition: tree.h:337
u_int16_t remote_port
Definition: dhclient.c:89
const char * file
Definition: dhcpd.h:3557
int can_unicast_without_arp(struct interface_info *)
struct executable_statement * on_commit
Definition: dhcpd.h:502
const unsigned char * data
Definition: tree.h:79
struct in_addr ciaddr
Definition: dhcp.h:56
struct binding_scope * scope
Definition: dhcpd.h:515
unsigned packet_length
Definition: dhcpd.h:372
u_int8_t op
Definition: dhcp.h:49
struct group * group
Definition: dhcpd.h:877