mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-02 15:25:48 +00:00
[master] Add use-host-decl-names support to BOOTP
Merges in rt36233.
This commit is contained in:
4
RELNOTES
4
RELNOTES
@@ -125,6 +125,10 @@ by Eric Young (eay@cryptsoft.com).
|
|||||||
[ISC-Bugs 35958]
|
[ISC-Bugs 35958]
|
||||||
[ISC-Bugs 32545]
|
[ISC-Bugs 32545]
|
||||||
|
|
||||||
|
- Added support of the configuration parameter, use-host-decl-names, to
|
||||||
|
BOOTP request handling.
|
||||||
|
[ISC-Bugs #36233]
|
||||||
|
|
||||||
Changes since 4.3.1b1
|
Changes since 4.3.1b1
|
||||||
|
|
||||||
- Modify the linux and openwrt dhclient scripts to process information
|
- Modify the linux and openwrt dhclient scripts to process information
|
||||||
|
@@ -43,17 +43,11 @@ static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
|
|||||||
struct option_cache **opp);
|
struct option_cache **opp);
|
||||||
|
|
||||||
/* Parse all available options out of the specified packet. */
|
/* Parse all available options out of the specified packet. */
|
||||||
|
/* Note, the caller is responsible for allocating packet->options. */
|
||||||
int parse_options (packet)
|
int parse_options (packet)
|
||||||
struct packet *packet;
|
struct packet *packet;
|
||||||
{
|
{
|
||||||
struct option_cache *op = (struct option_cache *)0;
|
struct option_cache *op = NULL;
|
||||||
|
|
||||||
/* Allocate a new option state. */
|
|
||||||
if (!option_state_allocate (&packet -> options, MDL)) {
|
|
||||||
packet -> options_valid = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we don't see the magic cookie, there's nothing to parse. */
|
/* If we don't see the magic cookie, there's nothing to parse. */
|
||||||
if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
|
if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
|
||||||
@@ -3856,12 +3850,15 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate packet->options now so it is non-null for all packets */
|
||||||
|
decoded_packet->options_valid = 0;
|
||||||
|
if (!option_state_allocate (&decoded_packet->options, MDL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* If there's an option buffer, try to parse it. */
|
/* If there's an option buffer, try to parse it. */
|
||||||
if (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
|
if (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
|
||||||
if (!parse_options(decoded_packet)) {
|
if (!parse_options(decoded_packet)) {
|
||||||
if (decoded_packet->options)
|
|
||||||
option_state_dereference
|
|
||||||
(&decoded_packet->options, MDL);
|
|
||||||
packet_dereference (&decoded_packet, MDL);
|
packet_dereference (&decoded_packet, MDL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -2072,7 +2072,7 @@ int evaluate_data_expression (result, packet, lease, client_state,
|
|||||||
((packet == NULL) ||
|
((packet == NULL) ||
|
||||||
(packet->dhcpv6_container_packet == NULL)))) {
|
(packet->dhcpv6_container_packet == NULL)))) {
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug("data: v6relay(%d) = NULL", len);
|
log_debug("data: v6relay(%lu) = NULL", len);
|
||||||
#endif
|
#endif
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -2090,7 +2090,7 @@ int evaluate_data_expression (result, packet, lease, client_state,
|
|||||||
/* We wanted a specific relay but were unable to find it */
|
/* We wanted a specific relay but were unable to find it */
|
||||||
if ((len <= MAX_V6RELAY_HOPS) && (i != 0)) {
|
if ((len <= MAX_V6RELAY_HOPS) && (i != 0)) {
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug("data: v6relay(%d) = NULL", len);
|
log_debug("data: v6relay(%lu) = NULL", len);
|
||||||
#endif
|
#endif
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -2107,7 +2107,7 @@ int evaluate_data_expression (result, packet, lease, client_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug("data: v6relay(%d) = %s", len,
|
log_debug("data: v6relay(%lu) = %s", len,
|
||||||
s1 ? print_hex_3(result->len, result->data, 30)
|
s1 ? print_hex_3(result->len, result->data, 30)
|
||||||
: "NULL");
|
: "NULL");
|
||||||
#endif
|
#endif
|
||||||
@@ -2664,9 +2664,16 @@ int evaluate_option_cache (result, packet, lease, client_state,
|
|||||||
oc -> expression, file, line);
|
oc -> expression, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate an option cache and extract a boolean from the result,
|
/* Evaluate an option cache and extract a boolean from the result.
|
||||||
returning the boolean. Return false if there is no data. */
|
* The boolean option cache is actually a trinary value where:
|
||||||
|
*
|
||||||
|
* 0 = return 0, ignore parameter 0 (also the case for no data)
|
||||||
|
* 1 = return 1, ignore parameter 0
|
||||||
|
* 2 = return 0, ignore parameter 1
|
||||||
|
*
|
||||||
|
* This supports both classic boolean flags on/off as well as the
|
||||||
|
* allow/deny/ignore keywords
|
||||||
|
*/
|
||||||
int evaluate_boolean_option_cache (ignorep, packet,
|
int evaluate_boolean_option_cache (ignorep, packet,
|
||||||
lease, client_state, in_options,
|
lease, client_state, in_options,
|
||||||
cfg_options, scope, oc, file, line)
|
cfg_options, scope, oc, file, line)
|
||||||
@@ -2681,37 +2688,36 @@ int evaluate_boolean_option_cache (ignorep, packet,
|
|||||||
const char *file;
|
const char *file;
|
||||||
int line;
|
int line;
|
||||||
{
|
{
|
||||||
struct data_string ds;
|
int result = 0;
|
||||||
int result;
|
if (ignorep)
|
||||||
|
*ignorep = 0;
|
||||||
|
|
||||||
/* So that we can be called with option_lookup as an argument. */
|
/* Only attempt to evaluate if option_cache is not null. This permits
|
||||||
if (!oc || !in_options)
|
* us to be called with option_lookup() as an argument. */
|
||||||
return 0;
|
if (oc && in_options) {
|
||||||
|
struct data_string ds;
|
||||||
|
|
||||||
memset (&ds, 0, sizeof ds);
|
memset(&ds, 0, sizeof ds);
|
||||||
if (!evaluate_option_cache (&ds, packet,
|
if (evaluate_option_cache(&ds, packet,
|
||||||
lease, client_state, in_options,
|
lease, client_state, in_options,
|
||||||
cfg_options, scope, oc, file, line))
|
cfg_options, scope, oc, file,
|
||||||
return 0;
|
line)) {
|
||||||
|
/* We have a value for the option set result and
|
||||||
|
* ignore parameter accordingly. */
|
||||||
|
if (ds.len) {
|
||||||
|
if (ds.data[0] == 1)
|
||||||
|
result = 1;
|
||||||
|
else if ((ds.data[0] == 2) && (ignorep != NULL))
|
||||||
|
*ignorep = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* The boolean option cache is actually a trinary value. Zero is
|
data_string_forget(&ds, MDL);
|
||||||
* off, one is on, and 2 is 'ignore'.
|
}
|
||||||
*/
|
}
|
||||||
if (ds.len) {
|
|
||||||
result = ds.data [0];
|
return (result);
|
||||||
if (result == 2) {
|
|
||||||
result = 0;
|
|
||||||
if (ignorep != NULL)
|
|
||||||
*ignorep = 1;
|
|
||||||
} else if (ignorep != NULL)
|
|
||||||
*ignorep = 0;
|
|
||||||
} else
|
|
||||||
result = 0;
|
|
||||||
data_string_forget (&ds, MDL);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Evaluate a boolean expression and return the result of the evaluation,
|
/* Evaluate a boolean expression and return the result of the evaluation,
|
||||||
or FALSE if it failed. */
|
or FALSE if it failed. */
|
||||||
|
|
||||||
|
@@ -2277,7 +2277,8 @@ isc_result_t get_client_id(struct packet *, struct data_string *);
|
|||||||
void dhcpv6(struct packet *);
|
void dhcpv6(struct packet *);
|
||||||
|
|
||||||
/* bootp.c */
|
/* bootp.c */
|
||||||
void bootp (struct packet *);
|
void bootp(struct packet *);
|
||||||
|
void use_host_decl_name(struct packet *, struct lease* , struct option_state *);
|
||||||
|
|
||||||
/* memory.c */
|
/* memory.c */
|
||||||
extern int (*group_write_hook) (struct group_object *);
|
extern int (*group_write_hook) (struct group_object *);
|
||||||
|
@@ -170,29 +170,29 @@ void bootp (packet)
|
|||||||
|
|
||||||
/* Execute the host statements. */
|
/* Execute the host statements. */
|
||||||
if (hp != NULL) {
|
if (hp != NULL) {
|
||||||
execute_statements_in_scope (NULL, packet, lease, NULL,
|
execute_statements_in_scope(NULL, packet, lease, NULL,
|
||||||
packet->options, options,
|
packet->options, options,
|
||||||
&lease->scope, hp->group,
|
&lease->scope, hp->group,
|
||||||
lease->subnet->group, NULL);
|
lease->subnet->group, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop the request if it's not allowed for this client. */
|
/* Drop the request if it's not allowed for this client. */
|
||||||
if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
|
if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
|
||||||
!evaluate_boolean_option_cache (&ignorep, packet, lease,
|
!evaluate_boolean_option_cache(&ignorep, packet, lease,
|
||||||
(struct client_state *)0,
|
NULL,
|
||||||
packet -> options, options,
|
packet->options, options,
|
||||||
&lease -> scope, oc, MDL)) {
|
&lease->scope, oc, MDL)) {
|
||||||
if (!ignorep)
|
if (!ignorep)
|
||||||
log_info ("%s: bootp disallowed", msgbuf);
|
log_info ("%s: bootp disallowed", msgbuf);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((oc = lookup_option (&server_universe,
|
if ((oc = lookup_option(&server_universe,
|
||||||
options, SV_ALLOW_BOOTING)) &&
|
options, SV_ALLOW_BOOTING)) &&
|
||||||
!evaluate_boolean_option_cache (&ignorep, packet, lease,
|
!evaluate_boolean_option_cache(&ignorep, packet, lease,
|
||||||
(struct client_state *)0,
|
NULL,
|
||||||
packet -> options, options,
|
packet->options, options,
|
||||||
&lease -> scope, oc, MDL)) {
|
&lease->scope, oc, MDL)) {
|
||||||
if (!ignorep)
|
if (!ignorep)
|
||||||
log_info ("%s: booting disallowed", msgbuf);
|
log_info ("%s: booting disallowed", msgbuf);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -205,20 +205,26 @@ void bootp (packet)
|
|||||||
|
|
||||||
/* If we didn't get a known vendor magic number on the way in,
|
/* If we didn't get a known vendor magic number on the way in,
|
||||||
just copy the input options to the output. */
|
just copy the input options to the output. */
|
||||||
if (!packet -> options_valid &&
|
i = SV_ALWAYS_REPLY_RFC1048;
|
||||||
!(evaluate_boolean_option_cache
|
if (!packet->options_valid &&
|
||||||
(&ignorep, packet, lease, (struct client_state *)0,
|
!(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
|
||||||
packet -> options, options, &lease -> scope,
|
packet->options, options,
|
||||||
lookup_option (&server_universe, options,
|
&lease->scope,
|
||||||
SV_ALWAYS_REPLY_RFC1048), MDL))) {
|
lookup_option (&server_universe,
|
||||||
memcpy (outgoing.raw -> options,
|
options, i), MDL))) {
|
||||||
packet -> raw -> options, DHCP_MAX_OPTION_LEN);
|
if (packet->packet_length > DHCP_FIXED_NON_UDP) {
|
||||||
outgoing.packet_length = BOOTP_MIN_LEN;
|
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;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
|
||||||
oc = (struct option_cache *)0;
|
oc = (struct option_cache *)0;
|
||||||
i = DHO_SUBNET_MASK;
|
i = DHO_SUBNET_MASK;
|
||||||
if (!lookup_option (&dhcp_universe, options, i)) {
|
if (!lookup_option (&dhcp_universe, options, i)) {
|
||||||
@@ -238,6 +244,11 @@ void bootp (packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
/* Pack the options into the buffer. Unlike DHCP, we
|
/* Pack the options into the buffer. Unlike DHCP, we
|
||||||
can't pack options into the filename and server
|
can't pack options into the filename and server
|
||||||
name buffers. */
|
name buffers. */
|
||||||
|
@@ -3216,33 +3216,10 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the hostname from the host declaration if there is one
|
/* Use the name of the host declaration if there is one
|
||||||
and no hostname has otherwise been provided, and if the
|
and no hostname has otherwise been provided, and if the
|
||||||
use-host-decl-name flag is set. */
|
use-host-decl-name flag is set. */
|
||||||
i = DHO_HOST_NAME;
|
use_host_decl_name(packet, lease, state->options);
|
||||||
j = SV_USE_HOST_DECL_NAMES;
|
|
||||||
if (!lookup_option (&dhcp_universe, state -> options, i) &&
|
|
||||||
lease -> host && lease -> host -> name &&
|
|
||||||
(evaluate_boolean_option_cache
|
|
||||||
(&ignorep, packet, lease, (struct client_state *)0,
|
|
||||||
packet -> options, state -> options, &lease -> scope,
|
|
||||||
lookup_option (&server_universe, state -> options, j), MDL))) {
|
|
||||||
oc = (struct option_cache *)0;
|
|
||||||
if (option_cache_allocate (&oc, MDL)) {
|
|
||||||
if (make_const_data (&oc -> expression,
|
|
||||||
((unsigned char *)
|
|
||||||
lease -> host -> name),
|
|
||||||
strlen (lease -> host -> name),
|
|
||||||
1, 0, MDL)) {
|
|
||||||
option_code_hash_lookup(&oc->option,
|
|
||||||
dhcp_universe.code_hash,
|
|
||||||
&i, 0, MDL);
|
|
||||||
save_option (&dhcp_universe,
|
|
||||||
state -> options, oc);
|
|
||||||
}
|
|
||||||
option_cache_dereference (&oc, MDL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send client_id back if we received it and echo-client-id is on. */
|
/* Send client_id back if we received it and echo-client-id is on. */
|
||||||
echo_client_id(packet, lease, state->options, state->options);
|
echo_client_id(packet, lease, state->options, state->options);
|
||||||
@@ -5144,3 +5121,44 @@ maybe_return_agent_options(struct packet *packet, struct option_state *options)
|
|||||||
options->universe_count = agent_universe.index + 1;
|
options->universe_count = agent_universe.index + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds hostname option when use-host-decl-names is enabled.
|
||||||
|
*
|
||||||
|
* Constructs a hostname option from the name of the host declaration if
|
||||||
|
* there is one and no hostname has otherwise been provided and the
|
||||||
|
* use-host-decl-names flag is set, then adds the new option to the given
|
||||||
|
* option_state. This funciton is used for both bootp and dhcp.
|
||||||
|
*
|
||||||
|
* \param packet inbound packet received from the client
|
||||||
|
* \param lease lease associated with the client
|
||||||
|
* \param options option state to search and update
|
||||||
|
*/
|
||||||
|
void use_host_decl_name(struct packet* packet,
|
||||||
|
struct lease *lease,
|
||||||
|
struct option_state *options) {
|
||||||
|
unsigned int ocode = SV_USE_HOST_DECL_NAMES;
|
||||||
|
if ((lease->host && lease->host->name) &&
|
||||||
|
!lookup_option(&dhcp_universe, options, DHO_HOST_NAME) &&
|
||||||
|
(evaluate_boolean_option_cache(NULL, packet, lease, NULL,
|
||||||
|
packet->options, options,
|
||||||
|
&lease->scope,
|
||||||
|
lookup_option(&server_universe,
|
||||||
|
options, ocode),
|
||||||
|
MDL))) {
|
||||||
|
struct option_cache *oc = NULL;
|
||||||
|
if (option_cache_allocate (&oc, MDL)) {
|
||||||
|
if (make_const_data(&oc -> expression,
|
||||||
|
((unsigned char*)lease->host->name),
|
||||||
|
strlen(lease->host->name),
|
||||||
|
1, 0, MDL)) {
|
||||||
|
ocode = DHO_HOST_NAME;
|
||||||
|
option_code_hash_lookup(&oc->option,
|
||||||
|
dhcp_universe.code_hash,
|
||||||
|
&ocode, 0, MDL);
|
||||||
|
save_option(&dhcp_universe, options, oc);
|
||||||
|
}
|
||||||
|
option_cache_dereference(&oc, MDL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user