mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-02 23:35:23 +00:00
Move some state into the lease structure so that we can test a lease before acking it, and so that we can do DNS lookups asynchronously
This commit is contained in:
434
server/dhcp.c
434
server/dhcp.c
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: dhcp.c,v 1.41 1997/03/05 06:18:55 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
|
"$Id: dhcp.c,v 1.42 1997/03/05 06:37:05 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"
|
||||||
@@ -409,15 +409,16 @@ void nak_lease (packet, cip)
|
|||||||
|
|
||||||
from = packet -> interface -> primary_address;
|
from = packet -> interface -> primary_address;
|
||||||
|
|
||||||
|
/* Make sure that the packet is at least as big as a BOOTP packet. */
|
||||||
|
if (outgoing.packet_length < BOOTP_MIN_LEN)
|
||||||
|
outgoing.packet_length = BOOTP_MIN_LEN;
|
||||||
|
|
||||||
/* If this was gatewayed, send it back to the gateway.
|
/* If this was gatewayed, send it back to the gateway.
|
||||||
Otherwise, broadcast it on the local network. */
|
Otherwise, broadcast it on the local network. */
|
||||||
if (raw.giaddr.s_addr) {
|
if (raw.giaddr.s_addr) {
|
||||||
to.sin_addr = raw.giaddr;
|
to.sin_addr = raw.giaddr;
|
||||||
to.sin_port = local_port;
|
to.sin_port = local_port;
|
||||||
|
|
||||||
if (outgoing.packet_length < BOOTP_MIN_LEN)
|
|
||||||
outgoing.packet_length = BOOTP_MIN_LEN;
|
|
||||||
|
|
||||||
#ifdef USE_FALLBACK
|
#ifdef USE_FALLBACK
|
||||||
result = send_fallback (&fallback_interface,
|
result = send_fallback (&fallback_interface,
|
||||||
packet, &raw, outgoing.packet_length,
|
packet, &raw, outgoing.packet_length,
|
||||||
@@ -449,31 +450,7 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
TIME lease_time;
|
TIME lease_time;
|
||||||
TIME offered_lease_time;
|
TIME offered_lease_time;
|
||||||
|
|
||||||
int bufs = 0;
|
|
||||||
struct packet outgoing;
|
|
||||||
struct dhcp_packet raw;
|
|
||||||
struct tree_cache *options [256];
|
|
||||||
struct sockaddr_in to;
|
|
||||||
struct in_addr from;
|
|
||||||
struct hardware hto;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
unsigned char lease_time_buf [4];
|
|
||||||
unsigned char lease_t1_buf [4];
|
|
||||||
unsigned char lease_t2_buf [4];
|
|
||||||
struct tree_cache lease_time_tree;
|
|
||||||
struct tree_cache lease_t1_tree;
|
|
||||||
struct tree_cache lease_t2_tree;
|
|
||||||
struct tree_cache dhcpoffer_tree;
|
|
||||||
struct tree_cache server_id_tree;
|
|
||||||
struct tree_cache vendor_class_tree;
|
|
||||||
struct tree_cache user_class_tree;
|
|
||||||
struct tree_cache hostname_tree;
|
|
||||||
struct tree_cache netmask_tree;
|
|
||||||
|
|
||||||
struct class *vendor_class, *user_class;
|
struct class *vendor_class, *user_class;
|
||||||
char *filename;
|
|
||||||
char *server_name;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (packet -> options [DHO_DHCP_CLASS_IDENTIFIER].len) {
|
if (packet -> options [DHO_DHCP_CLASS_IDENTIFIER].len) {
|
||||||
@@ -501,21 +478,21 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
/* 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)
|
||||||
filename = lease -> host -> group -> filename;
|
lease -> filename = lease -> host -> group -> filename;
|
||||||
else if (user_class && user_class -> group -> filename)
|
else if (user_class && user_class -> group -> filename)
|
||||||
filename = user_class -> group -> filename;
|
lease -> filename = user_class -> group -> filename;
|
||||||
else if (vendor_class && vendor_class -> group -> filename)
|
else if (vendor_class && vendor_class -> group -> filename)
|
||||||
filename = vendor_class -> group -> filename;
|
lease -> filename = vendor_class -> group -> filename;
|
||||||
else filename = (char *)0;
|
else lease -> filename = (char *)0;
|
||||||
|
|
||||||
/* Choose a server name as above. */
|
/* Choose a server name as above. */
|
||||||
if (lease -> host && lease -> host -> group -> server_name)
|
if (lease -> host && lease -> host -> group -> server_name)
|
||||||
server_name = lease -> host -> group -> server_name;
|
lease -> server_name = lease -> host -> group -> server_name;
|
||||||
else if (user_class && user_class -> group -> server_name)
|
else if (user_class && user_class -> group -> server_name)
|
||||||
server_name = user_class -> group -> server_name;
|
lease -> server_name = user_class -> group -> server_name;
|
||||||
else if (vendor_class && vendor_class -> group -> server_name)
|
else if (vendor_class && vendor_class -> group -> server_name)
|
||||||
server_name = vendor_class -> group -> server_name;
|
lease -> server_name = vendor_class -> group -> server_name;
|
||||||
else server_name = (char *)0;
|
else lease -> server_name = (char *)0;
|
||||||
|
|
||||||
/* At this point, we have a lease that we can offer the client.
|
/* At this point, we have a lease that we can offer the client.
|
||||||
Now we construct a lease structure that contains what we want,
|
Now we construct a lease structure that contains what we want,
|
||||||
@@ -589,13 +566,22 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
lt.timestamp = cur_time;
|
lt.timestamp = cur_time;
|
||||||
|
|
||||||
/* Record the uid, if given... */
|
/* Record the uid, if given... */
|
||||||
if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) {
|
i = DHO_DHCP_CLIENT_IDENTIFIER;
|
||||||
lt.uid_len =
|
if (packet -> options [i].len) {
|
||||||
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len;
|
if (packet -> options [i].len <= sizeof lt.uid_buf) {
|
||||||
lt.uid = packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data;
|
memcpy (lt.uid_buf, packet -> options [i].data,
|
||||||
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data =
|
packet -> options [i].len);
|
||||||
(unsigned char *)0;
|
lt.uid = lt.uid_buf;
|
||||||
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len = 0;
|
lt.uid_max = sizeof lt.uid_buf;
|
||||||
|
lt.uid_len = packet -> options [i].len;
|
||||||
|
} else {
|
||||||
|
lt.uid_max = lt.uid_len = packet -> options [i].len;
|
||||||
|
lt.uid = (unsigned char *)malloc (lt.uid_max);
|
||||||
|
if (!lt.uid)
|
||||||
|
error ("can't allocate memory for large uid.");
|
||||||
|
memcpy (lt.uid,
|
||||||
|
packet -> options [i].data, lt.uid_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the hardware address, if given... */
|
/* Record the hardware address, if given... */
|
||||||
@@ -622,42 +608,44 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
|| (offer && offer != DHCPACK)))
|
|| (offer && offer != DHCPACK)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Send a response to the client... */
|
/* Remember the interface on which the packet arrived. */
|
||||||
|
lease -> ip = packet -> interface;
|
||||||
|
|
||||||
memset (&outgoing, 0, sizeof outgoing);
|
/* Set a flag if this client is a lame Microsoft client that NUL
|
||||||
memset (&raw, 0, sizeof raw);
|
terminates string options and expects us to do likewise. */
|
||||||
outgoing.raw = &raw;
|
if (packet -> options [DHO_HOST_NAME].data &&
|
||||||
|
packet -> options [DHO_HOST_NAME].data
|
||||||
/* Copy in the filename if given; otherwise, flag the filename
|
[packet -> options [DHO_HOST_NAME].len - 1] == '\0')
|
||||||
buffer as available for options. */
|
lease -> flags |= MS_NULL_TERMINATION;
|
||||||
if (filename)
|
|
||||||
strncpy (raw.file, filename, sizeof raw.file);
|
|
||||||
else
|
else
|
||||||
bufs |= 1;
|
lease -> flags &= ~MS_NULL_TERMINATION;
|
||||||
|
|
||||||
/* Copy in the server name if given; otherwise, flag the
|
/* Remember the giaddr, xid, secs, flags and hops. */
|
||||||
server_name buffer as available for options. */
|
lease -> giaddr = packet -> raw -> giaddr;
|
||||||
if (server_name)
|
lease -> ciaddr = packet -> raw -> giaddr;
|
||||||
strncpy (raw.sname, server_name, sizeof raw.sname);
|
lease -> xid = packet -> raw -> xid;
|
||||||
else
|
lease -> secs = packet -> raw -> secs;
|
||||||
bufs |= 2; /* XXX */
|
lease -> bootp_flags = packet -> raw -> flags;
|
||||||
|
lease -> hops = packet -> raw -> hops;
|
||||||
|
lease -> offer = offer;
|
||||||
|
|
||||||
memcpy (raw.chaddr, packet -> raw -> chaddr, packet -> raw -> hlen);
|
/* Figure out what options to send to the client: */
|
||||||
raw.hlen = packet -> raw -> hlen;
|
|
||||||
raw.htype = packet -> raw -> htype;
|
|
||||||
|
|
||||||
/* Start out with the subnet options... */
|
/* Start out with the subnet options... */
|
||||||
memcpy (options, lease -> subnet -> group -> options, sizeof options);
|
memcpy (lease -> options,
|
||||||
|
lease -> subnet -> group -> options,
|
||||||
|
sizeof lease -> options);
|
||||||
|
|
||||||
/* Vendor and user classes are only supported for DHCP clients. */
|
/* Vendor and user classes are only supported for DHCP clients. */
|
||||||
if (offer) {
|
if (lease -> offer) {
|
||||||
/* If we have a vendor class, install those options,
|
/* If we have a vendor class, install those options,
|
||||||
superseding any subnet options. */
|
superseding any subnet options. */
|
||||||
if (vendor_class) {
|
if (vendor_class) {
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
if (vendor_class -> group -> options [i])
|
if (vendor_class -> group -> options [i])
|
||||||
options [i] = (vendor_class -> group ->
|
lease -> options [i] =
|
||||||
options [i]);
|
(vendor_class -> group ->
|
||||||
|
options [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a user class, install those options,
|
/* If we have a user class, install those options,
|
||||||
@@ -665,8 +653,9 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
if (user_class) {
|
if (user_class) {
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
if (user_class -> group -> options [i])
|
if (user_class -> group -> options [i])
|
||||||
options [i] = (user_class -> group ->
|
lease -> options [i] =
|
||||||
options [i]);
|
(user_class -> group ->
|
||||||
|
options [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -676,45 +665,45 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
if (lease -> host) {
|
if (lease -> host) {
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
if (lease -> host -> group -> options [i])
|
if (lease -> host -> group -> options [i])
|
||||||
options [i] = (lease -> host ->
|
lease -> options [i] = (lease -> host ->
|
||||||
group -> options [i]);
|
group -> options [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't get a hostname from an option somewhere, see if
|
/* If we didn't get a hostname from an option somewhere, see if
|
||||||
we can get one from the lease. */
|
we can get one from the lease. */
|
||||||
if (!options [DHO_HOST_NAME] && lease -> hostname) {
|
i = DHO_HOST_NAME;
|
||||||
options [DHO_HOST_NAME] = &hostname_tree;
|
if (!lease -> options [i] && lease -> hostname) {
|
||||||
options [DHO_HOST_NAME] -> value =
|
lease -> options [i] = new_tree_cache ("hostname");
|
||||||
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
|
lease -> options [i] -> value =
|
||||||
(unsigned char *)lease -> hostname;
|
(unsigned char *)lease -> hostname;
|
||||||
options [DHO_HOST_NAME] -> buf_size =
|
lease -> options [i] -> len = strlen (lease -> hostname);
|
||||||
options [DHO_HOST_NAME] -> len =
|
lease -> options [i] -> buf_size = lease -> options [i] -> len;
|
||||||
strlen (lease -> hostname);
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
options [DHO_HOST_NAME] -> timeout = 0xFFFFFFFF;
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
options [DHO_HOST_NAME] -> tree = (struct tree *)0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, if appropriate, put in DHCP-specific options that
|
/* Now, if appropriate, put in DHCP-specific options that
|
||||||
override those. */
|
override those. */
|
||||||
if (offer) {
|
if (lease -> offer) {
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] = &dhcpoffer_tree;
|
i = DHO_DHCP_MESSAGE_TYPE;
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] -> value = &offer;
|
lease -> options [i] = new_tree_cache ("message-type");
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof offer;
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof offer;
|
lease -> options [i] -> value = &lease -> offer;
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
|
lease -> options [i] -> len = sizeof lease -> offer;
|
||||||
options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
|
lease -> options [i] -> buf_size = sizeof lease -> offer;
|
||||||
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
|
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] = &server_id_tree;
|
i = DHO_DHCP_SERVER_IDENTIFIER;
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] -> value =
|
lease -> options [i] = new_tree_cache ("server-id");
|
||||||
(unsigned char *)
|
lease -> options [i] -> value =
|
||||||
&packet -> interface -> primary_address;
|
(unsigned char *)&lease -> ip -> primary_address;
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] -> len =
|
lease -> options [i] -> len =
|
||||||
sizeof packet -> interface -> primary_address;
|
sizeof lease -> ip -> primary_address;
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] -> buf_size =
|
lease -> options [i] -> buf_size = lease -> options [i] -> len;
|
||||||
sizeof packet -> interface -> primary_address;
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] -> timeout =
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
0xFFFFFFFF;
|
|
||||||
options [DHO_DHCP_SERVER_IDENTIFIER] -> tree =
|
|
||||||
(struct tree *)0;
|
|
||||||
|
|
||||||
/* Sanity check the lease time. */
|
/* Sanity check the lease time. */
|
||||||
if ((lease->offered_expiry - cur_time) < 15)
|
if ((lease->offered_expiry - cur_time) < 15)
|
||||||
@@ -728,97 +717,157 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
offered_lease_time =
|
offered_lease_time =
|
||||||
lease -> offered_expiry - cur_time;
|
lease -> offered_expiry - cur_time;
|
||||||
|
|
||||||
putULong (lease_time_buf, offered_lease_time);
|
putULong ((unsigned char *)&lease -> expiry,
|
||||||
options [DHO_DHCP_LEASE_TIME] = &lease_time_tree;
|
offered_lease_time);
|
||||||
options [DHO_DHCP_LEASE_TIME] -> value = lease_time_buf;
|
i = DHO_DHCP_LEASE_TIME;
|
||||||
options [DHO_DHCP_LEASE_TIME] -> len = sizeof lease_time_buf;
|
lease -> options [i] = new_tree_cache ("lease-expiry");
|
||||||
options [DHO_DHCP_LEASE_TIME] ->
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
buf_size = sizeof lease_time_buf;
|
lease -> options [i] -> value =
|
||||||
options [DHO_DHCP_LEASE_TIME] -> timeout = 0xFFFFFFFF;
|
(unsigned char *)&lease -> expiry;
|
||||||
options [DHO_DHCP_LEASE_TIME] -> tree = (struct tree *)0;
|
lease -> options [i] -> len = sizeof lease -> expiry;
|
||||||
|
lease -> options [i] -> buf_size = sizeof lease -> expiry;
|
||||||
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
|
|
||||||
/* Renewal time is lease time * 0.5. */
|
/* Renewal time is lease time * 0.5. */
|
||||||
offered_lease_time /= 2;
|
offered_lease_time /= 2;
|
||||||
putULong (lease_t1_buf, offered_lease_time);
|
putULong ((unsigned char *)&lease -> renewal,
|
||||||
options [DHO_DHCP_RENEWAL_TIME] = &lease_t1_tree;
|
offered_lease_time);
|
||||||
options [DHO_DHCP_RENEWAL_TIME] -> value = lease_t1_buf;
|
i = DHO_DHCP_RENEWAL_TIME;
|
||||||
options [DHO_DHCP_RENEWAL_TIME] -> len = sizeof lease_t1_buf;
|
lease -> options [i] = new_tree_cache ("renewal-time");
|
||||||
options [DHO_DHCP_RENEWAL_TIME] ->
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
buf_size = sizeof lease_t1_buf;
|
lease -> options [i] -> value =
|
||||||
options [DHO_DHCP_RENEWAL_TIME] -> timeout = 0xFFFFFFFF;
|
(unsigned char *)&lease -> renewal;
|
||||||
options [DHO_DHCP_RENEWAL_TIME] -> tree = (struct tree *)0;
|
lease -> options [i] -> len = sizeof lease -> renewal;
|
||||||
|
lease -> options [i] -> buf_size = sizeof lease -> renewal;
|
||||||
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
|
|
||||||
|
|
||||||
/* Rebinding time is lease time * 0.875. */
|
/* Rebinding time is lease time * 0.875. */
|
||||||
offered_lease_time += (offered_lease_time / 2
|
offered_lease_time += (offered_lease_time / 2
|
||||||
+ offered_lease_time / 4);
|
+ offered_lease_time / 4);
|
||||||
putULong (lease_t2_buf, offered_lease_time);
|
putULong ((unsigned char *)&lease -> rebind,
|
||||||
options [DHO_DHCP_REBINDING_TIME] = &lease_t2_tree;
|
offered_lease_time);
|
||||||
options [DHO_DHCP_REBINDING_TIME] -> value = lease_t2_buf;
|
i = DHO_DHCP_REBINDING_TIME;
|
||||||
options [DHO_DHCP_REBINDING_TIME] -> len = sizeof lease_t2_buf;
|
lease -> options [i] = new_tree_cache ("rebind-time");
|
||||||
options [DHO_DHCP_REBINDING_TIME] ->
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
buf_size = sizeof lease_t2_buf;
|
lease -> options [i] -> value =
|
||||||
options [DHO_DHCP_REBINDING_TIME] -> timeout = 0xFFFFFFFF;
|
(unsigned char *)&lease -> rebind;
|
||||||
options [DHO_DHCP_REBINDING_TIME] -> tree = (struct tree *)0;
|
lease -> options [i] -> len = sizeof lease -> rebind;
|
||||||
|
lease -> options [i] -> buf_size = sizeof lease -> rebind;
|
||||||
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
|
|
||||||
/* If we used the vendor class the client specified, we
|
/* If we used the vendor class the client specified, we
|
||||||
have to return it. */
|
have to return it. */
|
||||||
if (vendor_class) {
|
if (vendor_class) {
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] =
|
i = DHO_DHCP_CLASS_IDENTIFIER;
|
||||||
&vendor_class_tree;
|
lease -> options [i] =
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] ->
|
new_tree_cache ("class-identifier");
|
||||||
value = (unsigned char *)vendor_class -> name;
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] ->
|
lease -> options [i] -> value =
|
||||||
len = strlen (vendor_class -> name);
|
(unsigned char *)vendor_class -> name;
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] ->
|
lease -> options [i] -> len =
|
||||||
buf_size = strlen (vendor_class -> name);
|
strlen (vendor_class -> name);
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] ->
|
lease -> options [i] -> buf_size =
|
||||||
timeout = 0xFFFFFFFF;
|
lease -> options [i] -> len;
|
||||||
options [DHO_DHCP_CLASS_IDENTIFIER] ->
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
tree = (struct tree *)0;
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we used the user class the client specified, we
|
/* If we used the user class the client specified, we
|
||||||
have to return it. */
|
have to return it. */
|
||||||
if (user_class) {
|
if (user_class) {
|
||||||
options [DHO_DHCP_USER_CLASS_ID] = &user_class_tree;
|
i = DHO_DHCP_USER_CLASS_ID;
|
||||||
options [DHO_DHCP_USER_CLASS_ID] ->
|
lease -> options [i] = new_tree_cache ("user-class");
|
||||||
value = (unsigned char *)user_class -> name;
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
options [DHO_DHCP_USER_CLASS_ID] ->
|
lease -> options [i] -> value =
|
||||||
len = strlen (user_class -> name);
|
(unsigned char *)user_class -> name;
|
||||||
options [DHO_DHCP_USER_CLASS_ID] ->
|
lease -> options [i] -> len =
|
||||||
buf_size = strlen (user_class -> name);
|
strlen (user_class -> name);
|
||||||
options [DHO_DHCP_USER_CLASS_ID] ->
|
lease -> options [i] -> buf_size =
|
||||||
timeout = 0xFFFFFFFF;
|
lease -> options [i] -> len;
|
||||||
options [DHO_DHCP_USER_CLASS_ID] ->
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
tree = (struct tree *)0;
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the subnet mask from the subnet declaration if no other
|
/* Use the subnet mask from the subnet declaration if no other
|
||||||
mask has been provided. */
|
mask has been provided. */
|
||||||
if (!options [DHO_SUBNET_MASK]) {
|
i = DHO_SUBNET_MASK;
|
||||||
options [DHO_SUBNET_MASK] = &netmask_tree;
|
if (!lease -> options [i]) {
|
||||||
netmask_tree.value = lease -> subnet -> netmask.iabuf;
|
lease -> options [i] = new_tree_cache ("subnet-mask");
|
||||||
netmask_tree.len = lease -> subnet -> netmask.len;
|
lease -> options [i] -> flags = TC_TEMPORARY;
|
||||||
netmask_tree.buf_size = lease -> subnet -> netmask.len;
|
lease -> options [i] -> value =
|
||||||
netmask_tree.timeout = 0xFFFFFFFF;
|
lease -> subnet -> netmask.iabuf;
|
||||||
netmask_tree.tree = (struct tree *)0;
|
lease -> options [i] -> len = lease -> subnet -> netmask.len;
|
||||||
|
lease -> options [i] -> buf_size =
|
||||||
|
lease -> subnet -> netmask.len;
|
||||||
|
lease -> options [i] -> timeout = 0xFFFFFFFF;
|
||||||
|
lease -> options [i] -> tree = (struct tree *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_PACKET
|
||||||
|
dump_packet (packet);
|
||||||
|
dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dhcp_reply (lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dhcp_reply (lease)
|
||||||
|
struct lease *lease;
|
||||||
|
{
|
||||||
|
int bufs = 0;
|
||||||
|
int packet_length;
|
||||||
|
struct dhcp_packet raw;
|
||||||
|
struct sockaddr_in to;
|
||||||
|
struct in_addr from;
|
||||||
|
struct hardware hto;
|
||||||
|
int result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Send a response to the client... */
|
||||||
|
memset (&raw, 0, sizeof raw);
|
||||||
|
|
||||||
|
/* Copy in the filename if given; otherwise, flag the filename
|
||||||
|
buffer as available for options. */
|
||||||
|
if (lease -> filename)
|
||||||
|
strncpy (raw.file, lease -> filename, sizeof raw.file);
|
||||||
|
else
|
||||||
|
bufs |= 1;
|
||||||
|
|
||||||
|
/* Copy in the server name if given; otherwise, flag the
|
||||||
|
server_name buffer as available for options. */
|
||||||
|
if (lease -> server_name)
|
||||||
|
strncpy (raw.sname, lease -> server_name, sizeof raw.sname);
|
||||||
|
else
|
||||||
|
bufs |= 2; /* XXX */
|
||||||
|
|
||||||
|
memcpy (raw.chaddr, lease -> hardware_addr.haddr,
|
||||||
|
lease -> hardware_addr.hlen);
|
||||||
|
raw.hlen = lease -> hardware_addr.hlen;
|
||||||
|
raw.htype = lease -> hardware_addr.htype;
|
||||||
|
|
||||||
/* See if this is a Microsoft client that NUL-terminates its
|
/* See if this is a Microsoft client that NUL-terminates its
|
||||||
strings and expects us to do likewise... */
|
strings and expects us to do likewise... */
|
||||||
if (packet -> options [DHO_HOST_NAME].data &&
|
if (lease -> flags & MS_NULL_TERMINATION)
|
||||||
packet -> options [DHO_HOST_NAME].data
|
packet_length = cons_options ((struct packet *)0,
|
||||||
[packet -> options [DHO_HOST_NAME].len - 1] == '\0')
|
&raw, lease -> options, bufs, 1);
|
||||||
outgoing.packet_length =
|
|
||||||
cons_options (packet, outgoing.raw, options, bufs, 1);
|
|
||||||
else
|
else
|
||||||
outgoing.packet_length =
|
packet_length = cons_options ((struct packet *)0,
|
||||||
cons_options (packet, outgoing.raw, options, bufs, 0);
|
&raw, lease -> options, bufs, 0);
|
||||||
if (!offer && outgoing.packet_length < BOOTP_MIN_LEN)
|
|
||||||
outgoing.packet_length = BOOTP_MIN_LEN;
|
|
||||||
|
|
||||||
raw.ciaddr = packet -> raw -> ciaddr;
|
/* Having done the cons_options(), we can release the tree_cache
|
||||||
|
entries. */
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
if (lease -> options [i] &&
|
||||||
|
lease -> options [i] -> flags & TC_TEMPORARY)
|
||||||
|
free_tree_cache (lease -> options [i], "dhcp_reply");
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&raw.ciaddr, &lease -> ciaddr, sizeof raw.ciaddr);
|
||||||
memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
|
memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
|
||||||
|
|
||||||
/* Figure out the address of the next server. */
|
/* Figure out the address of the next server. */
|
||||||
@@ -832,33 +881,33 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
memcpy (&raw.siaddr,
|
memcpy (&raw.siaddr,
|
||||||
lease -> subnet -> interface_address.iabuf, 4);
|
lease -> subnet -> interface_address.iabuf, 4);
|
||||||
else
|
else
|
||||||
raw.siaddr = packet -> interface -> primary_address;
|
raw.siaddr = lease -> ip -> primary_address;
|
||||||
|
|
||||||
raw.giaddr = packet -> raw -> giaddr;
|
raw.giaddr = lease -> giaddr;
|
||||||
|
|
||||||
raw.xid = packet -> raw -> xid;
|
raw.xid = lease -> xid;
|
||||||
raw.secs = packet -> raw -> secs;
|
raw.secs = lease -> secs;
|
||||||
raw.flags = packet -> raw -> flags;
|
raw.flags = lease -> bootp_flags;
|
||||||
raw.hops = packet -> raw -> hops;
|
raw.hops = lease -> hops;
|
||||||
raw.op = BOOTREPLY;
|
raw.op = BOOTREPLY;
|
||||||
|
|
||||||
/* Say what we're doing... */
|
/* Say what we're doing... */
|
||||||
note ("%s on %s to %s via %s",
|
note ("%s on %s to %s via %s",
|
||||||
(offer
|
(lease -> offer
|
||||||
? (offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
|
? (lease -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
|
||||||
: "BOOTREPLY"),
|
: "BOOTREPLY"),
|
||||||
piaddr (lease -> ip_addr),
|
piaddr (lease -> ip_addr),
|
||||||
print_hw_addr (packet -> raw -> htype,
|
print_hw_addr (lease -> hardware_addr.htype,
|
||||||
packet -> raw -> hlen,
|
lease -> hardware_addr.hlen,
|
||||||
packet -> raw -> chaddr),
|
lease -> hardware_addr.haddr),
|
||||||
packet -> raw -> giaddr.s_addr
|
lease -> giaddr.s_addr
|
||||||
? inet_ntoa (packet -> raw -> giaddr)
|
? inet_ntoa (lease -> giaddr)
|
||||||
: packet -> interface -> name);
|
: lease -> ip -> name);
|
||||||
|
|
||||||
/* Set up the hardware address... */
|
/* Set up the hardware address... */
|
||||||
hto.htype = packet -> raw -> htype;
|
hto.htype = lease -> hardware_addr.htype;
|
||||||
hto.hlen = packet -> raw -> hlen;
|
hto.hlen = lease -> hardware_addr.hlen;
|
||||||
memcpy (hto.haddr, packet -> raw -> chaddr, hto.hlen);
|
memcpy (hto.haddr, lease -> hardware_addr.haddr, hto.hlen);
|
||||||
|
|
||||||
to.sin_family = AF_INET;
|
to.sin_family = AF_INET;
|
||||||
#ifdef HAVE_SA_LEN
|
#ifdef HAVE_SA_LEN
|
||||||
@@ -866,26 +915,26 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
#endif
|
#endif
|
||||||
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
||||||
|
|
||||||
from = packet -> interface -> primary_address;
|
from = lease -> ip -> primary_address;
|
||||||
|
|
||||||
#ifdef DEBUG_PACKET
|
#ifdef DEBUG_PACKET
|
||||||
dump_packet (packet);
|
dump_raw ((unsigned char *)&raw, packet_length);
|
||||||
dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
|
|
||||||
dump_packet (&outgoing);
|
|
||||||
dump_raw ((unsigned char *)&raw, outgoing.packet_length);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Make sure outgoing packets are at least as big
|
||||||
|
as a BOOTP packet. */
|
||||||
|
if (packet_length < BOOTP_MIN_LEN)
|
||||||
|
packet_length = BOOTP_MIN_LEN;
|
||||||
|
|
||||||
/* If this was gatewayed, send it back to the gateway... */
|
/* If this was gatewayed, send it back to the gateway... */
|
||||||
if (raw.giaddr.s_addr) {
|
if (raw.giaddr.s_addr) {
|
||||||
to.sin_addr = raw.giaddr;
|
to.sin_addr = raw.giaddr;
|
||||||
to.sin_port = local_port;
|
to.sin_port = local_port;
|
||||||
|
|
||||||
if (outgoing.packet_length < BOOTP_MIN_LEN)
|
|
||||||
outgoing.packet_length = BOOTP_MIN_LEN;
|
|
||||||
|
|
||||||
#ifdef USE_FALLBACK
|
#ifdef USE_FALLBACK
|
||||||
result = send_fallback (&fallback_interface,
|
result = send_fallback (&fallback_interface,
|
||||||
packet, &raw, outgoing.packet_length,
|
(struct packet *)0,
|
||||||
|
&raw, packet_length,
|
||||||
raw.siaddr, &to, &hto);
|
raw.siaddr, &to, &hto);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
warn ("send_fallback: %m");
|
warn ("send_fallback: %m");
|
||||||
@@ -895,14 +944,15 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
/* If it comes from a client who already knows its address and
|
/* If it comes from a client who already knows its address and
|
||||||
is not requesting a broadcast response, sent it directly to
|
is not requesting a broadcast response, sent it directly to
|
||||||
that client. */
|
that client. */
|
||||||
} else if (raw.ciaddr.s_addr && offer == DHCPACK &&
|
} else if (raw.ciaddr.s_addr && lease -> offer == DHCPACK &&
|
||||||
!(raw.flags & htons (BOOTP_BROADCAST))) {
|
!(raw.flags & htons (BOOTP_BROADCAST))) {
|
||||||
to.sin_addr = packet -> raw -> ciaddr;
|
to.sin_addr = lease -> ciaddr;
|
||||||
to.sin_port = remote_port; /* XXX */
|
to.sin_port = remote_port; /* XXX */
|
||||||
|
|
||||||
#ifdef USE_FALLBACK
|
#ifdef USE_FALLBACK
|
||||||
result = send_fallback (&fallback_interface,
|
result = send_fallback (&fallback_interface,
|
||||||
packet, &raw, outgoing.packet_length,
|
(struct packet *)0,
|
||||||
|
&raw, packet_length,
|
||||||
raw.siaddr, &to, &hto);
|
raw.siaddr, &to, &hto);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
warn ("send_fallback: %m");
|
warn ("send_fallback: %m");
|
||||||
@@ -916,8 +966,8 @@ void ack_lease (packet, lease, offer, when)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result = send_packet (packet -> interface,
|
result = send_packet (lease -> ip,
|
||||||
packet, &raw, outgoing.packet_length,
|
(struct packet *)0, &raw, packet_length,
|
||||||
raw.siaddr, &to, &hto);
|
raw.siaddr, &to, &hto);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
warn ("sendpkt: %m");
|
warn ("sendpkt: %m");
|
||||||
|
Reference in New Issue
Block a user