2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-02 07:15:44 +00:00

[master] Add use-host-decl-names support to BOOTP

Merges in rt36233.
This commit is contained in:
Thomas Markwalder
2014-10-27 14:51:20 -04:00
parent e046c82621
commit 0a7e1a8ab0
6 changed files with 130 additions and 93 deletions

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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,36 +2688,35 @@ 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);
if (!evaluate_option_cache (&ds, packet,
lease, client_state, in_options,
cfg_options, scope, oc, file, line))
return 0;
/* The boolean option cache is actually a trinary value. Zero is memset(&ds, 0, sizeof ds);
* off, one is on, and 2 is 'ignore'. if (evaluate_option_cache(&ds, packet,
*/ lease, client_state, in_options,
if (ds.len) { cfg_options, scope, oc, file,
result = ds.data [0]; line)) {
if (result == 2) { /* We have a value for the option set result and
result = 0; * ignore parameter accordingly. */
if (ignorep != NULL) if (ds.len) {
*ignorep = 1; if (ds.data[0] == 1)
} else if (ignorep != NULL) result = 1;
*ignorep = 0; else if ((ds.data[0] == 2) && (ignorep != NULL))
} else *ignorep = 1;
result = 0; }
data_string_forget (&ds, MDL);
return result; 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. */

View File

@@ -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 *);

View File

@@ -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. */

View File

@@ -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);
}
}
}