1995-11-29 07:40:04 +00:00
|
|
|
/* bootp.c
|
|
|
|
|
|
|
|
BOOTP Protocol support. */
|
|
|
|
|
|
|
|
/*
|
2017-07-12 09:23:23 -04:00
|
|
|
* Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
|
2005-03-17 20:15:29 +00:00
|
|
|
* Copyright (c) 1995-2003 by Internet Software Consortium
|
1995-11-29 07:40:04 +00:00
|
|
|
*
|
2017-07-12 09:23:23 -04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
1995-11-29 07:40:04 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1995-11-29 07:40:04 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* Internet Systems Consortium, Inc.
|
2022-01-19 20:13:19 +01:00
|
|
|
* PO Box 360
|
|
|
|
* Newmarket, NH 03857 USA
|
2005-03-17 20:15:29 +00:00
|
|
|
* <info@isc.org>
|
2009-07-23 18:52:21 +00:00
|
|
|
* https://www.isc.org/
|
2000-03-17 04:00:32 +00:00
|
|
|
*
|
1995-11-29 07:40:04 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
2007-05-19 18:47:15 +00:00
|
|
|
#include <errno.h>
|
1995-11-29 07:40:04 +00:00
|
|
|
|
2001-02-12 20:51:26 +00:00
|
|
|
#if defined (TRACING)
|
|
|
|
# define send_packet trace_packet_send
|
|
|
|
#endif
|
|
|
|
|
1995-11-29 07:40:04 +00:00
|
|
|
void bootp (packet)
|
|
|
|
struct packet *packet;
|
|
|
|
{
|
|
|
|
int result;
|
2000-05-16 23:03:49 +00:00
|
|
|
struct host_decl *hp = (struct host_decl *)0;
|
1996-05-22 07:14:13 +00:00
|
|
|
struct host_decl *host = (struct host_decl *)0;
|
1996-03-06 10:38:04 +00:00
|
|
|
struct packet outgoing;
|
|
|
|
struct dhcp_packet raw;
|
1995-11-29 07:40:04 +00:00
|
|
|
struct sockaddr_in to;
|
1996-08-27 09:33:41 +00:00
|
|
|
struct in_addr from;
|
1996-05-12 23:55:27 +00:00
|
|
|
struct hardware hto;
|
1999-04-05 16:34:33 +00:00
|
|
|
struct option_state *options = (struct option_state *)0;
|
2005-07-07 16:39:08 +00:00
|
|
|
struct lease *lease = (struct lease *)0;
|
1999-10-07 06:36:35 +00:00
|
|
|
unsigned i;
|
1998-06-25 03:41:03 +00:00
|
|
|
struct data_string d1;
|
1998-11-05 18:54:55 +00:00
|
|
|
struct option_cache *oc;
|
1998-11-11 07:57:21 +00:00
|
|
|
char msgbuf [1024];
|
1999-10-21 02:38:06 +00:00
|
|
|
int ignorep;
|
2000-05-03 22:57:42 +00:00
|
|
|
int peer_has_leases = 0;
|
1995-11-29 07:40:04 +00:00
|
|
|
|
1997-05-09 08:20:12 +00:00
|
|
|
if (packet -> raw -> op != BOOTREQUEST)
|
|
|
|
return;
|
|
|
|
|
2005-03-17 20:15:29 +00:00
|
|
|
/* %Audit% This is log output. %2004.06.17,Safe%
|
|
|
|
* If we truncate we hope the user can get a hint from the log.
|
|
|
|
*/
|
|
|
|
snprintf (msgbuf, sizeof msgbuf, "BOOTREQUEST from %s via %s",
|
1998-11-11 07:57:21 +00:00
|
|
|
print_hw_addr (packet -> raw -> htype,
|
|
|
|
packet -> raw -> hlen,
|
|
|
|
packet -> raw -> chaddr),
|
|
|
|
packet -> raw -> giaddr.s_addr
|
|
|
|
? inet_ntoa (packet -> raw -> giaddr)
|
|
|
|
: packet -> interface -> name);
|
1996-06-01 00:02:36 +00:00
|
|
|
|
1998-11-11 07:57:21 +00:00
|
|
|
if (!locate_network (packet)) {
|
1999-02-24 17:56:53 +00:00
|
|
|
log_info ("%s: network unknown", msgbuf);
|
1996-08-27 09:33:41 +00:00
|
|
|
return;
|
1998-11-11 07:57:21 +00:00
|
|
|
}
|
1996-05-22 09:29:56 +00:00
|
|
|
|
2000-11-28 23:27:24 +00:00
|
|
|
find_lease (&lease, packet, packet -> shared_network,
|
|
|
|
0, 0, (struct lease *)0, MDL);
|
1996-05-22 07:14:13 +00:00
|
|
|
|
2005-07-07 16:39:08 +00:00
|
|
|
if (lease && lease->host)
|
|
|
|
host_reference(&hp, lease->host, MDL);
|
1996-05-22 07:14:13 +00:00
|
|
|
|
2005-07-07 16:39:08 +00:00
|
|
|
if (!lease || ((lease->flags & STATIC_LEASE) == 0)) {
|
2000-05-16 23:03:49 +00:00
|
|
|
struct host_decl *h;
|
2007-10-03 20:15:15 +00:00
|
|
|
|
2005-07-07 16:39:08 +00:00
|
|
|
/* We didn't find an applicable fixed-address host
|
|
|
|
declaration. Just in case we may be able to dynamically
|
|
|
|
assign an address, see if there's a host declaration
|
1996-05-22 07:14:13 +00:00
|
|
|
that doesn't have an ip address associated with it. */
|
2005-07-07 16:39:08 +00:00
|
|
|
|
|
|
|
if (!hp)
|
|
|
|
find_hosts_by_haddr(&hp, packet->raw->htype,
|
|
|
|
packet->raw->chaddr,
|
|
|
|
packet->raw->hlen, MDL);
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
for (h = hp; h; h = h -> n_ipaddr) {
|
|
|
|
if (!h -> fixed_addr) {
|
2005-07-07 16:39:08 +00:00
|
|
|
host_reference(&host, h, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
break;
|
1996-05-22 07:14:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-07 16:39:08 +00:00
|
|
|
if (hp)
|
|
|
|
host_dereference(&hp, MDL);
|
|
|
|
|
|
|
|
if (host) {
|
|
|
|
host_reference(&hp, host, MDL);
|
|
|
|
host_dereference(&host, MDL);
|
1996-05-22 07:14:13 +00:00
|
|
|
}
|
2005-03-17 20:15:29 +00:00
|
|
|
|
2005-07-07 16:39:08 +00:00
|
|
|
/* Allocate a lease if we have not yet found one. */
|
|
|
|
if (!lease)
|
|
|
|
allocate_lease (&lease, packet,
|
|
|
|
packet -> shared_network -> pools,
|
|
|
|
&peer_has_leases);
|
|
|
|
|
2007-10-03 20:15:15 +00:00
|
|
|
if (lease == NULL) {
|
|
|
|
log_info("%s: BOOTP from dynamic client and no "
|
|
|
|
"dynamic leases", msgbuf);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
if ((lease->pool != NULL) &&
|
|
|
|
(lease->pool->failover_peer != NULL)) {
|
|
|
|
dhcp_failover_state_t *peer;
|
|
|
|
|
|
|
|
peer = lease->pool->failover_peer;
|
|
|
|
|
|
|
|
/* If we are in a failover state that bars us from
|
|
|
|
* answering, do not do so.
|
|
|
|
* If we are in a cooperative state, load balance
|
|
|
|
* (all) responses.
|
|
|
|
*/
|
|
|
|
if ((peer->service_state == not_responding) ||
|
|
|
|
(peer->service_state == service_startup)) {
|
|
|
|
log_info("%s: not responding%s",
|
|
|
|
msgbuf, peer->nrr);
|
|
|
|
goto out;
|
|
|
|
} else if((peer->service_state == cooperating) &&
|
|
|
|
!load_balance_mine(packet, peer)) {
|
|
|
|
log_info("%s: load balance to peer %s",
|
|
|
|
msgbuf, peer->name);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2005-07-07 16:39:08 +00:00
|
|
|
|
2007-10-03 20:15:15 +00:00
|
|
|
ack_lease (packet, lease, 0, 0, msgbuf, 0, hp);
|
2000-05-16 23:03:49 +00:00
|
|
|
goto out;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
1996-03-06 10:38:04 +00:00
|
|
|
|
1998-06-25 03:41:03 +00:00
|
|
|
/* Run the executable statements to compute the client and server
|
|
|
|
options. */
|
2000-01-25 01:36:29 +00:00
|
|
|
option_state_allocate (&options, MDL);
|
2005-07-07 16:39:08 +00:00
|
|
|
|
1998-06-25 03:41:03 +00:00
|
|
|
/* Execute the subnet statements. */
|
2013-08-27 13:40:47 -07:00
|
|
|
execute_statements_in_scope (NULL, packet, lease, NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope, lease->subnet->group,
|
|
|
|
NULL, NULL);
|
2005-07-07 16:39:08 +00:00
|
|
|
|
1999-06-10 00:36:27 +00:00
|
|
|
/* Execute statements from class scopes. */
|
|
|
|
for (i = packet -> class_count; i > 0; i--) {
|
2013-08-27 13:40:47 -07:00
|
|
|
execute_statements_in_scope(NULL, packet, lease, NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope,
|
|
|
|
packet->classes[i - 1]->group,
|
|
|
|
lease->subnet->group, NULL);
|
1999-06-10 00:36:27 +00:00
|
|
|
}
|
|
|
|
|
1998-06-25 03:41:03 +00:00
|
|
|
/* Execute the host statements. */
|
2012-04-10 21:26:44 +00:00
|
|
|
if (hp != NULL) {
|
2014-10-27 14:51:20 -04:00
|
|
|
execute_statements_in_scope(NULL, packet, lease, NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope, hp->group,
|
|
|
|
lease->subnet->group, NULL);
|
2012-04-10 21:26:44 +00:00
|
|
|
}
|
2022-01-19 20:14:16 +01:00
|
|
|
|
1998-06-25 03:41:03 +00:00
|
|
|
/* Drop the request if it's not allowed for this client. */
|
1999-10-20 16:47:04 +00:00
|
|
|
if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
|
2014-10-27 14:51:20 -04:00
|
|
|
!evaluate_boolean_option_cache(&ignorep, packet, lease,
|
|
|
|
NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope, oc, MDL)) {
|
1999-10-21 02:38:06 +00:00
|
|
|
if (!ignorep)
|
|
|
|
log_info ("%s: bootp disallowed", msgbuf);
|
2000-05-16 23:03:49 +00:00
|
|
|
goto out;
|
2022-01-19 20:14:16 +01:00
|
|
|
}
|
1998-06-25 03:41:03 +00:00
|
|
|
|
2014-10-27 14:51:20 -04:00
|
|
|
if ((oc = lookup_option(&server_universe,
|
1999-10-20 16:47:04 +00:00
|
|
|
options, SV_ALLOW_BOOTING)) &&
|
2014-10-27 14:51:20 -04:00
|
|
|
!evaluate_boolean_option_cache(&ignorep, packet, lease,
|
|
|
|
NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope, oc, MDL)) {
|
1999-10-21 02:38:06 +00:00
|
|
|
if (!ignorep)
|
|
|
|
log_info ("%s: booting disallowed", msgbuf);
|
2000-05-16 23:03:49 +00:00
|
|
|
goto out;
|
1997-02-22 08:36:36 +00:00
|
|
|
}
|
1998-06-25 03:41:03 +00:00
|
|
|
|
1996-03-06 10:38:04 +00:00
|
|
|
/* Set up the outgoing packet... */
|
|
|
|
memset (&outgoing, 0, sizeof outgoing);
|
|
|
|
memset (&raw, 0, sizeof raw);
|
|
|
|
outgoing.raw = &raw;
|
|
|
|
|
1998-02-06 01:05:39 +00:00
|
|
|
/* If we didn't get a known vendor magic number on the way in,
|
|
|
|
just copy the input options to the output. */
|
2014-10-27 14:51:20 -04:00
|
|
|
i = SV_ALWAYS_REPLY_RFC1048;
|
|
|
|
if (!packet->options_valid &&
|
|
|
|
!(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
|
|
|
|
packet->options, options,
|
|
|
|
&lease->scope,
|
|
|
|
lookup_option (&server_universe,
|
|
|
|
options, i), MDL))) {
|
|
|
|
if (packet->packet_length > DHCP_FIXED_NON_UDP) {
|
|
|
|
memcpy(outgoing.raw->options, packet->raw->options,
|
|
|
|
packet->packet_length - DHCP_FIXED_NON_UDP);
|
|
|
|
}
|
|
|
|
|
|
|
|
outgoing.packet_length =
|
|
|
|
(packet->packet_length < BOOTP_MIN_LEN)
|
|
|
|
? BOOTP_MIN_LEN
|
|
|
|
: packet->packet_length;
|
1998-02-06 01:05:39 +00:00
|
|
|
} else {
|
1999-04-08 19:36:23 +00:00
|
|
|
|
|
|
|
/* Use the subnet mask from the subnet declaration if no other
|
|
|
|
mask has been provided. */
|
|
|
|
oc = (struct option_cache *)0;
|
|
|
|
i = DHO_SUBNET_MASK;
|
|
|
|
if (!lookup_option (&dhcp_universe, options, i)) {
|
2000-01-25 01:36:29 +00:00
|
|
|
if (option_cache_allocate (&oc, MDL)) {
|
1999-04-08 19:36:23 +00:00
|
|
|
if (make_const_data
|
|
|
|
(&oc -> expression,
|
|
|
|
lease -> subnet -> netmask.iabuf,
|
2001-06-27 00:31:20 +00:00
|
|
|
lease -> subnet -> netmask.len,
|
|
|
|
0, 0, MDL)) {
|
2006-06-01 20:23:18 +00:00
|
|
|
option_code_hash_lookup(&oc->option,
|
|
|
|
dhcp_universe.code_hash,
|
|
|
|
&i, 0, MDL);
|
1999-04-08 19:36:23 +00:00
|
|
|
save_option (&dhcp_universe,
|
|
|
|
options, oc);
|
|
|
|
}
|
2000-01-25 01:36:29 +00:00
|
|
|
option_cache_dereference (&oc, MDL);
|
1999-04-08 19:36:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 14:51:20 -04:00
|
|
|
/* If use-host-decl-names is enabled and there is a hostname
|
|
|
|
* defined in the host delcartion, send it back in hostname
|
|
|
|
* option */
|
|
|
|
use_host_decl_name(packet, lease, options);
|
|
|
|
|
1998-02-06 01:05:39 +00:00
|
|
|
/* Pack the options into the buffer. Unlike DHCP, we
|
|
|
|
can't pack options into the filename and server
|
|
|
|
name buffers. */
|
1996-03-06 10:38:04 +00:00
|
|
|
|
1998-02-06 01:05:39 +00:00
|
|
|
outgoing.packet_length =
|
2000-11-28 23:27:24 +00:00
|
|
|
cons_options (packet, outgoing.raw, lease,
|
|
|
|
(struct client_state *)0, 0,
|
1999-07-31 18:07:16 +00:00
|
|
|
packet -> options, options,
|
2000-01-25 01:36:29 +00:00
|
|
|
&lease -> scope,
|
2000-10-10 23:01:05 +00:00
|
|
|
0, 0, 1, (struct data_string *)0,
|
|
|
|
(const char *)0);
|
1998-02-06 01:05:39 +00:00
|
|
|
if (outgoing.packet_length < BOOTP_MIN_LEN)
|
|
|
|
outgoing.packet_length = BOOTP_MIN_LEN;
|
|
|
|
}
|
1996-03-06 10:38:04 +00:00
|
|
|
|
1995-11-29 07:40:04 +00:00
|
|
|
/* Take the fields that we care about... */
|
1996-03-06 10:38:04 +00:00
|
|
|
raw.op = BOOTREPLY;
|
|
|
|
raw.htype = packet -> raw -> htype;
|
|
|
|
raw.hlen = packet -> raw -> hlen;
|
1998-02-06 01:05:39 +00:00
|
|
|
memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
|
1996-03-06 10:38:04 +00:00
|
|
|
raw.hops = packet -> raw -> hops;
|
|
|
|
raw.xid = packet -> raw -> xid;
|
|
|
|
raw.secs = packet -> raw -> secs;
|
1999-06-22 13:25:23 +00:00
|
|
|
raw.flags = packet -> raw -> flags;
|
1996-03-06 10:38:04 +00:00
|
|
|
raw.ciaddr = packet -> raw -> ciaddr;
|
2005-07-07 16:39:08 +00:00
|
|
|
|
|
|
|
/* yiaddr is an ipv4 address, it must be 4 octets. */
|
|
|
|
memcpy (&raw.yiaddr, lease->ip_addr.iabuf, 4);
|
1996-05-22 07:14:13 +00:00
|
|
|
|
1999-06-22 13:25:23 +00:00
|
|
|
/* If we're always supposed to broadcast to this client, set
|
|
|
|
the broadcast bit in the bootp flags field. */
|
1999-07-01 20:02:58 +00:00
|
|
|
if ((oc = lookup_option (&server_universe,
|
|
|
|
options, SV_ALWAYS_BROADCAST)) &&
|
1999-10-21 02:38:06 +00:00
|
|
|
evaluate_boolean_option_cache (&ignorep, packet, lease,
|
2000-11-28 23:27:24 +00:00
|
|
|
(struct client_state *)0,
|
2000-01-25 01:36:29 +00:00
|
|
|
packet -> options, options,
|
|
|
|
&lease -> scope, oc, MDL))
|
1999-06-22 13:25:23 +00:00
|
|
|
raw.flags |= htons (BOOTP_BROADCAST);
|
|
|
|
|
1996-08-27 09:33:41 +00:00
|
|
|
/* Figure out the address of the next server. */
|
1999-03-30 18:12:34 +00:00
|
|
|
memset (&d1, 0, sizeof d1);
|
1999-05-27 14:58:07 +00:00
|
|
|
oc = lookup_option (&server_universe, options, SV_NEXT_SERVER);
|
1998-11-05 18:54:55 +00:00
|
|
|
if (oc &&
|
1999-07-31 18:07:16 +00:00
|
|
|
evaluate_option_cache (&d1, packet, lease,
|
2000-11-28 23:27:24 +00:00
|
|
|
(struct client_state *)0,
|
2000-01-25 01:36:29 +00:00
|
|
|
packet -> options, options,
|
|
|
|
&lease -> scope, oc, MDL)) {
|
1998-06-25 03:41:03 +00:00
|
|
|
/* If there was more than one answer, take the first. */
|
|
|
|
if (d1.len >= 4 && d1.data)
|
|
|
|
memcpy (&raw.siaddr, d1.data, 4);
|
2000-01-25 01:36:29 +00:00
|
|
|
data_string_forget (&d1, MDL);
|
1999-04-12 22:15:38 +00:00
|
|
|
} else {
|
2007-05-08 23:05:22 +00:00
|
|
|
if ((lease->subnet->shared_network->interface != NULL) &&
|
|
|
|
lease->subnet->shared_network->interface->address_count)
|
|
|
|
raw.siaddr =
|
|
|
|
lease->subnet->shared_network->interface->addresses[0];
|
|
|
|
else if (packet->interface->address_count)
|
|
|
|
raw.siaddr = packet->interface->addresses[0];
|
1998-06-25 03:41:03 +00:00
|
|
|
}
|
1996-05-22 07:14:13 +00:00
|
|
|
|
1996-03-06 10:38:04 +00:00
|
|
|
raw.giaddr = packet -> raw -> giaddr;
|
1998-06-25 03:41:03 +00:00
|
|
|
|
|
|
|
/* Figure out the filename. */
|
1999-05-27 14:58:07 +00:00
|
|
|
oc = lookup_option (&server_universe, options, SV_FILENAME);
|
1998-11-05 18:54:55 +00:00
|
|
|
if (oc &&
|
1999-07-31 18:07:16 +00:00
|
|
|
evaluate_option_cache (&d1, packet, lease,
|
2000-11-28 23:27:24 +00:00
|
|
|
(struct client_state *)0,
|
2000-01-25 01:36:29 +00:00
|
|
|
packet -> options, options,
|
|
|
|
&lease -> scope, oc, MDL)) {
|
1998-06-25 03:41:03 +00:00
|
|
|
memcpy (raw.file, d1.data,
|
|
|
|
d1.len > sizeof raw.file ? sizeof raw.file : d1.len);
|
|
|
|
if (sizeof raw.file > d1.len)
|
|
|
|
memset (&raw.file [d1.len],
|
|
|
|
0, (sizeof raw.file) - d1.len);
|
2000-01-25 01:36:29 +00:00
|
|
|
data_string_forget (&d1, MDL);
|
1999-02-14 19:40:22 +00:00
|
|
|
} else
|
1999-02-14 19:06:57 +00:00
|
|
|
memcpy (raw.file, packet -> raw -> file, sizeof raw.file);
|
1998-06-25 03:41:03 +00:00
|
|
|
|
|
|
|
/* Choose a server name as above. */
|
1999-05-27 14:58:07 +00:00
|
|
|
oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
|
1998-11-05 18:54:55 +00:00
|
|
|
if (oc &&
|
1999-07-31 18:07:16 +00:00
|
|
|
evaluate_option_cache (&d1, packet, lease,
|
2000-11-28 23:27:24 +00:00
|
|
|
(struct client_state *)0,
|
2000-01-25 01:36:29 +00:00
|
|
|
packet -> options, options,
|
|
|
|
&lease -> scope, oc, MDL)) {
|
1998-06-25 03:41:03 +00:00
|
|
|
memcpy (raw.sname, d1.data,
|
|
|
|
d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len);
|
|
|
|
if (sizeof raw.sname > d1.len)
|
|
|
|
memset (&raw.sname [d1.len],
|
|
|
|
0, (sizeof raw.sname) - d1.len);
|
2000-01-25 01:36:29 +00:00
|
|
|
data_string_forget (&d1, MDL);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
1999-07-18 19:38:33 +00:00
|
|
|
/* Execute the commit statements, if there are any. */
|
2013-08-27 13:40:47 -07:00
|
|
|
execute_statements (NULL, packet, lease, NULL, packet->options,
|
|
|
|
options, &lease->scope, lease->on_star.on_commit,
|
|
|
|
NULL);
|
1999-07-18 19:38:33 +00:00
|
|
|
|
1999-04-05 16:34:33 +00:00
|
|
|
/* We're done with the option state. */
|
2000-01-25 01:36:29 +00:00
|
|
|
option_state_dereference (&options, MDL);
|
1999-04-05 16:34:33 +00:00
|
|
|
|
2016-02-23 10:40:10 +01:00
|
|
|
#if defined(DHCPv6) && defined(DHCP4o6)
|
|
|
|
if (dhcpv4_over_dhcpv6 && (packet->dhcp4o6_response != NULL)) {
|
|
|
|
/* Report what we're doing... */
|
|
|
|
log_info("%s", msgbuf);
|
|
|
|
log_info("DHCP4o6 BOOTREPLY for %s to %s (%s) via %s",
|
|
|
|
piaddr(lease->ip_addr),
|
|
|
|
((hp != NULL) && (hp->name != NULL)) ?
|
|
|
|
hp -> name : "unknown",
|
|
|
|
print_hw_addr (packet->raw->htype,
|
|
|
|
packet->raw->hlen,
|
|
|
|
packet->raw->chaddr),
|
|
|
|
piaddr(packet->client_addr));
|
|
|
|
|
|
|
|
/* fill dhcp4o6_response */
|
|
|
|
packet->dhcp4o6_response->len = outgoing.packet_length;
|
|
|
|
packet->dhcp4o6_response->buffer = NULL;
|
|
|
|
if (!buffer_allocate(&packet->dhcp4o6_response->buffer,
|
|
|
|
outgoing.packet_length, MDL)) {
|
|
|
|
log_fatal("No memory to store DHCP4o6 reply.");
|
|
|
|
}
|
|
|
|
packet->dhcp4o6_response->data =
|
|
|
|
packet->dhcp4o6_response->buffer->data;
|
|
|
|
memcpy(packet->dhcp4o6_response->buffer->data,
|
|
|
|
outgoing.raw, outgoing.packet_length);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1996-05-22 07:14:13 +00:00
|
|
|
/* Set up the hardware destination address... */
|
2000-01-05 18:17:10 +00:00
|
|
|
hto.hbuf [0] = packet -> raw -> htype;
|
|
|
|
hto.hlen = packet -> raw -> hlen + 1;
|
2000-09-20 00:06:04 +00:00
|
|
|
memcpy (&hto.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
|
1996-05-22 07:14:13 +00:00
|
|
|
|
2008-08-20 23:07:19 +00:00
|
|
|
if (packet->interface->address_count) {
|
2007-05-08 23:05:22 +00:00
|
|
|
from = packet->interface->addresses[0];
|
2008-08-20 23:07:19 +00:00
|
|
|
} else {
|
|
|
|
log_error("%s: Interface %s appears to have no IPv4 "
|
|
|
|
"addresses, and so dhcpd cannot select a source "
|
|
|
|
"address.", msgbuf, packet->interface->name);
|
|
|
|
goto out;
|
|
|
|
}
|
1996-08-27 09:33:41 +00:00
|
|
|
|
1996-05-22 07:14:13 +00:00
|
|
|
/* Report what we're doing... */
|
2012-04-10 21:26:44 +00:00
|
|
|
log_info("%s", msgbuf);
|
|
|
|
log_info("BOOTREPLY for %s to %s (%s) via %s",
|
|
|
|
piaddr(lease->ip_addr),
|
|
|
|
((hp != NULL) && (hp->name != NULL)) ? hp -> name : "unknown",
|
|
|
|
print_hw_addr (packet->raw->htype,
|
|
|
|
packet->raw->hlen,
|
|
|
|
packet->raw->chaddr),
|
|
|
|
packet->raw->giaddr.s_addr
|
|
|
|
? inet_ntoa (packet->raw->giaddr)
|
|
|
|
: packet->interface->name);
|
1996-05-22 07:14:13 +00:00
|
|
|
|
|
|
|
/* Set up the parts of the address that are in common. */
|
|
|
|
to.sin_family = AF_INET;
|
|
|
|
#ifdef HAVE_SA_LEN
|
|
|
|
to.sin_len = sizeof to;
|
|
|
|
#endif
|
|
|
|
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
|
|
|
|
1996-03-06 10:38:04 +00:00
|
|
|
/* If this was gatewayed, send it back to the gateway... */
|
|
|
|
if (raw.giaddr.s_addr) {
|
|
|
|
to.sin_addr = raw.giaddr;
|
1997-02-19 10:50:40 +00:00
|
|
|
to.sin_port = local_port;
|
1996-05-22 07:14:13 +00:00
|
|
|
|
1999-02-14 19:06:57 +00:00
|
|
|
if (fallback_interface) {
|
2012-03-09 11:18:14 +00:00
|
|
|
result = send_packet (fallback_interface, NULL, &raw,
|
|
|
|
outgoing.packet_length, from,
|
|
|
|
&to, &hto);
|
|
|
|
if (result < 0) {
|
|
|
|
log_error ("%s:%d: Failed to send %d byte long "
|
|
|
|
"packet over %s interface.", MDL,
|
|
|
|
outgoing.packet_length,
|
|
|
|
fallback_interface->name);
|
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
goto out;
|
1999-02-14 19:06:57 +00:00
|
|
|
}
|
1999-10-20 16:47:04 +00:00
|
|
|
|
|
|
|
/* If it comes from a client that already knows its address
|
|
|
|
and is not requesting a broadcast response, and we can
|
|
|
|
unicast to a client without using the ARP protocol, sent it
|
|
|
|
directly to that client. */
|
|
|
|
} else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
|
|
|
|
can_unicast_without_arp (packet -> interface)) {
|
|
|
|
to.sin_addr = raw.yiaddr;
|
|
|
|
to.sin_port = remote_port;
|
|
|
|
|
1996-03-06 10:38:04 +00:00
|
|
|
/* Otherwise, broadcast it on the local network. */
|
|
|
|
} else {
|
1999-07-06 17:09:03 +00:00
|
|
|
to.sin_addr = limited_broadcast;
|
1997-02-19 10:50:40 +00:00
|
|
|
to.sin_port = remote_port; /* XXX */
|
1996-03-06 10:38:04 +00:00
|
|
|
}
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
errno = 0;
|
2012-03-09 11:18:14 +00:00
|
|
|
result = send_packet(packet->interface, packet, &raw,
|
|
|
|
outgoing.packet_length, from, &to, &hto);
|
|
|
|
if (result < 0) {
|
|
|
|
log_error ("%s:%d: Failed to send %d byte long packet over %s"
|
|
|
|
" interface.", MDL, outgoing.packet_length,
|
|
|
|
packet->interface->name);
|
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
out:
|
2012-03-09 11:18:14 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
if (options)
|
|
|
|
option_state_dereference (&options, MDL);
|
2001-05-17 19:04:09 +00:00
|
|
|
if (lease)
|
2000-05-16 23:03:49 +00:00
|
|
|
lease_dereference (&lease, MDL);
|
|
|
|
if (hp)
|
|
|
|
host_dereference (&hp, MDL);
|
|
|
|
if (host)
|
|
|
|
host_dereference (&host, MDL);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|