mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-30 05:47:45 +00:00
Fix bug introduced into dhcprequest processing. Fix core dump differently. Store client-supplied hostname. Fix ciaddr copy.
This commit is contained in:
parent
00d6d87c9e
commit
44b2e3adb2
@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef lint
|
||||
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 */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -178,8 +178,9 @@ void dhcprequest (packet)
|
||||
|
||||
/* Find the lease that matches the address requested by the
|
||||
client. */
|
||||
if (packet -> shared_network)
|
||||
lease = find_lease (packet, packet -> shared_network);
|
||||
|
||||
if (subnet)
|
||||
lease = find_lease (packet, subnet -> shared_network);
|
||||
else
|
||||
lease = (struct lease *)0;
|
||||
|
||||
@ -192,25 +193,50 @@ void dhcprequest (packet)
|
||||
? inet_ntoa (packet -> raw -> giaddr)
|
||||
: packet -> interface -> name);
|
||||
|
||||
/* If a client on a given network wants to request a lease on
|
||||
an address on a different network, NAK it. If the Requested
|
||||
Address option was used, the protocol says that it must have
|
||||
been broadcast, so we can trust the source network information.
|
||||
/* If a client on a given network REQUESTs a lease on an
|
||||
address on a different network, NAK it. If the Requested
|
||||
Address option was used, the protocol says that it must
|
||||
have been broadcast, so we can trust the source network
|
||||
information.
|
||||
|
||||
If ciaddr was specified and Requested Address was not, then
|
||||
we really only know for sure what network a packet came from
|
||||
if it came through a BOOTP gateway - if it came through an
|
||||
IP router, we'll just have to assume that it's cool.
|
||||
|
||||
This violates the protocol spec in the case that the client
|
||||
is in the INIT-REBOOT state and broadcasts a DHCPREQUEST on
|
||||
the local wire. We're supposed to check ciaddr for
|
||||
validity in that case, but if the packet was unicast
|
||||
through a router from a client in the RENEWING state, it
|
||||
would look exactly the same to us and it would be very
|
||||
bad to send a DHCPNAK. I think we just have to live with
|
||||
this. */
|
||||
if ((packet -> raw -> ciaddr.s_addr &&
|
||||
If we don't think we know where the packet came from, it
|
||||
came through a gateway from an unknown network, so it's not
|
||||
from a RENEWING client. If we recognize the network it
|
||||
*thinks* it's on, we can NAK it even though we don't
|
||||
recognize the network it's *actually* on; otherwise we just
|
||||
have to ignore it.
|
||||
|
||||
We don't currently try to take advantage of access to the
|
||||
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 -> options [DHO_DHCP_REQUESTED_ADDRESS].len) {
|
||||
|
||||
@ -226,9 +252,8 @@ void dhcprequest (packet)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we do know where it came from and either we don't
|
||||
know where it came from at all or it came from a different
|
||||
shared network than the packet came from, send a nak. */
|
||||
/* If we do know where it came from and it asked for an
|
||||
address that is not on that shared network, nak it. */
|
||||
subnet = find_grouped_subnet (packet -> shared_network, cip);
|
||||
if (!subnet) {
|
||||
nak_lease (packet, &cip);
|
||||
@ -430,7 +455,7 @@ void nak_lease (packet, cip)
|
||||
#endif
|
||||
} else {
|
||||
to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
|
||||
to.sin_port = packet->client_port;
|
||||
to.sin_port = remote_port;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
@ -489,6 +514,31 @@ void ack_lease (packet, lease, offer, when)
|
||||
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
|
||||
the user class, then from the vendor class. */
|
||||
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. */
|
||||
state -> giaddr = packet -> raw -> giaddr;
|
||||
state -> ciaddr = packet -> raw -> giaddr;
|
||||
state -> ciaddr = packet -> raw -> ciaddr;
|
||||
state -> xid = packet -> raw -> xid;
|
||||
state -> secs = packet -> raw -> secs;
|
||||
state -> bootp_flags = packet -> raw -> flags;
|
||||
|
Loading…
x
Reference in New Issue
Block a user