2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-01 06:45:27 +00:00

Fix bug introduced into dhcprequest processing. Fix core dump differently. Store client-supplied hostname. Fix ciaddr copy.

This commit is contained in:
Ted Lemon
1997-05-09 08:27:14 +00:00
parent 00d6d87c9e
commit 44b2e3adb2

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: dhcp.c,v 1.46 1997/03/06 20:23:27 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: dhcp.c,v 1.47 1997/05/09 08:27:14 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -178,8 +178,9 @@ void dhcprequest (packet)
/* Find the lease that matches the address requested by the /* Find the lease that matches the address requested by the
client. */ client. */
if (packet -> shared_network)
lease = find_lease (packet, packet -> shared_network); if (subnet)
lease = find_lease (packet, subnet -> shared_network);
else else
lease = (struct lease *)0; lease = (struct lease *)0;
@@ -192,25 +193,50 @@ void dhcprequest (packet)
? inet_ntoa (packet -> raw -> giaddr) ? inet_ntoa (packet -> raw -> giaddr)
: packet -> interface -> name); : packet -> interface -> name);
/* If a client on a given network wants to request a lease on /* If a client on a given network REQUESTs a lease on an
an address on a different network, NAK it. If the Requested address on a different network, NAK it. If the Requested
Address option was used, the protocol says that it must have Address option was used, the protocol says that it must
been broadcast, so we can trust the source network information. have been broadcast, so we can trust the source network
information.
If ciaddr was specified and Requested Address was not, then If ciaddr was specified and Requested Address was not, then
we really only know for sure what network a packet came from we really only know for sure what network a packet came from
if it came through a BOOTP gateway - if it came through an if it came through a BOOTP gateway - if it came through an
IP router, we'll just have to assume that it's cool. IP router, we'll just have to assume that it's cool.
This violates the protocol spec in the case that the client If we don't think we know where the packet came from, it
is in the INIT-REBOOT state and broadcasts a DHCPREQUEST on came through a gateway from an unknown network, so it's not
the local wire. We're supposed to check ciaddr for from a RENEWING client. If we recognize the network it
validity in that case, but if the packet was unicast *thinks* it's on, we can NAK it even though we don't
through a router from a client in the RENEWING state, it recognize the network it's *actually* on; otherwise we just
would look exactly the same to us and it would be very have to ignore it.
bad to send a DHCPNAK. I think we just have to live with
this. */ We don't currently try to take advantage of access to the
if ((packet -> raw -> ciaddr.s_addr && raw packet, because it's not available on all platforms.
So a packet that was unicast to us through a router from a
RENEWING client is going to look exactly like a packet that
was broadcast to us from an INIT-REBOOT client.
Since we can't tell the difference between these two kinds
of packets, if the packet appears to have come in off the
local wire, we have to treat it as if it's a RENEWING
client. This means that we can't NAK a RENEWING client on
the local wire that has a bogus address. The good news is
that we won't ACK it either, so it should revert to INIT
state and send us a DHCPDISCOVER, which we *can* work with.
Because we can't detect that a RENEWING client is on the
wrong wire, it's going to sit there trying to renew until
it gets to the REBIND state, when we *can* NAK it because
the packet will get to us through a BOOTP gateway. We
shouldn't actually see DHCPREQUEST packets from RENEWING
clients on the wrong wire anyway, since their idea of their
local router will be wrong. In any case, the protocol
doesn't really allow us to NAK a DHCPREQUEST from a
RENEWING client, so we can punt on this issue. */
if (!packet -> shared_network ||
(packet -> raw -> ciaddr.s_addr &&
packet -> raw -> giaddr.s_addr) || packet -> raw -> giaddr.s_addr) ||
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) {
@@ -226,9 +252,8 @@ void dhcprequest (packet)
return; return;
} }
/* If we do know where it came from and either we don't /* If we do know where it came from and it asked for an
know where it came from at all or it came from a different address that is not on that shared network, nak it. */
shared network than the packet came from, send a nak. */
subnet = find_grouped_subnet (packet -> shared_network, cip); subnet = find_grouped_subnet (packet -> shared_network, cip);
if (!subnet) { if (!subnet) {
nak_lease (packet, &cip); nak_lease (packet, &cip);
@@ -430,7 +455,7 @@ void nak_lease (packet, cip)
#endif #endif
} else { } else {
to.sin_addr.s_addr = htonl (INADDR_BROADCAST); to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
to.sin_port = packet->client_port; to.sin_port = remote_port;
} }
errno = 0; errno = 0;
@@ -489,6 +514,31 @@ void ack_lease (packet, lease, offer, when)
user_class = (struct class *)0; user_class = (struct class *)0;
} }
/* Replace the old lease hostname with the new one, if it's changed. */
if (packet -> options [DHO_HOST_NAME].len &&
lease -> client_hostname &&
(strlen (lease -> client_hostname) ==
packet -> options [DHO_HOST_NAME].len) &&
!memcmp (lease -> client_hostname,
packet -> options [DHO_HOST_NAME].data,
packet -> options [DHO_HOST_NAME].len)) {
} else if (packet -> options [DHO_HOST_NAME].len) {
if (lease -> client_hostname)
free (lease -> client_hostname);
lease -> client_hostname =
malloc (packet -> options [DHO_HOST_NAME].len + 1);
if (!lease -> client_hostname)
error ("no memory for client hostname.\n");
memcpy (lease -> client_hostname,
packet -> options [DHO_HOST_NAME].data,
packet -> options [DHO_HOST_NAME].len);
lease -> client_hostname
[packet -> options [DHO_HOST_NAME].len] = 0;
} else if (lease -> client_hostname) {
free (lease -> client_hostname);
lease -> client_hostname = 0;
}
/* Choose a filename; first from the host_decl, if any, then from /* Choose a filename; first from the host_decl, if any, then from
the user class, then from the vendor class. */ the user class, then from the vendor class. */
if (lease -> host && lease -> host -> group -> filename) if (lease -> host && lease -> host -> group -> filename)
@@ -633,7 +683,7 @@ void ack_lease (packet, lease, offer, when)
/* Remember the giaddr, xid, secs, flags and hops. */ /* Remember the giaddr, xid, secs, flags and hops. */
state -> giaddr = packet -> raw -> giaddr; state -> giaddr = packet -> raw -> giaddr;
state -> ciaddr = packet -> raw -> giaddr; state -> ciaddr = packet -> raw -> ciaddr;
state -> xid = packet -> raw -> xid; state -> xid = packet -> raw -> xid;
state -> secs = packet -> raw -> secs; state -> secs = packet -> raw -> secs;
state -> bootp_flags = packet -> raw -> flags; state -> bootp_flags = packet -> raw -> flags;