diff options
-rw-r--r-- | .gitignore | 24 | ||||
-rw-r--r-- | RELNOTES | 6 | ||||
-rw-r--r-- | common/options.c | 19 | ||||
-rw-r--r-- | common/tree.c | 66 | ||||
-rw-r--r-- | includes/dhcpd.h | 3 | ||||
-rw-r--r-- | server/bootp.c | 49 | ||||
-rw-r--r-- | server/dhcp.c | 67 |
7 files changed, 147 insertions, 87 deletions
@@ -4,3 +4,27 @@ doc/html .deps Makefile autom4te.cache +client/dhclient +client/tests/ +common/tests/alloc_unittest +common/tests/dns_unittest +common/tests/misc_unittest +config.log +config.report +config.status +dhcpctl/cltest +dhcpctl/omshell +doc/devel/doxyfile +dst/libdst.a +includes/.dhcpd.h.swp +includes/stamp-h1 +omapip/svtest +relay/dhcrelay +server/dhcpd +server/tests/dhcpd_unittests +server/tests/hash_unittests +server/tests/legacy_unittests +server/tests/load_bal_unittests +server/tests/test-suite.log +tests/libt_api.a +minires/libres.a @@ -103,11 +103,15 @@ by Eric Young (eay@cryptsoft.com). [ISC-Bus #24216] [ISC-Bus #25587] +- Added support of the configuration parameter, use-host-decl-names, to + BOOTP request handling. + [ISC-Bugs #36233] + Changes since 4.1-ESV-R10rc1 - None - Changes since 4.1-ESV-R10b1 + Changes since 4.3.1b1 - Modify the linux and openwrt dhclient scripts to process information from a stateless request. Thanks to Jiri Popelka at Red Hat for the diff --git a/common/options.c b/common/options.c index db8d8071..140a1aea 100644 --- a/common/options.c +++ b/common/options.c @@ -43,17 +43,11 @@ static int prepare_option_buffer(struct universe *universe, struct buffer *bp, struct option_cache **opp); /* Parse all available options out of the specified packet. */ - +/* Note, the caller is responsible for allocating packet->options. */ int parse_options (packet) struct packet *packet; { - struct option_cache *op = (struct option_cache *)0; - - /* Allocate a new option state. */ - if (!option_state_allocate (&packet -> options, MDL)) { - packet -> options_valid = 0; - return 0; - } + struct option_cache *op = NULL; /* If we don't see the magic cookie, there's nothing to parse. */ if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) { @@ -3790,12 +3784,15 @@ void do_packet (interface, packet, len, from_port, from, hfrom) 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 (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) { if (!parse_options(decoded_packet)) { - if (decoded_packet->options) - option_state_dereference - (&decoded_packet->options, MDL); packet_dereference (&decoded_packet, MDL); return; } diff --git a/common/tree.c b/common/tree.c index ef3e3091..838dbcaa 100644 --- a/common/tree.c +++ b/common/tree.c @@ -2900,9 +2900,16 @@ int evaluate_option_cache (result, packet, lease, client_state, oc -> expression, file, line); } -/* Evaluate an option cache and extract a boolean from the result, - returning the boolean. Return false if there is no data. */ - +/* Evaluate an option cache and extract a boolean from the result. + * 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, lease, client_state, in_options, cfg_options, scope, oc, file, line) @@ -2917,36 +2924,35 @@ int evaluate_boolean_option_cache (ignorep, packet, const char *file; int line; { - struct data_string ds; - int result; + int result = 0; + if (ignorep) + *ignorep = 0; - /* So that we can be called with option_lookup as an argument. */ - if (!oc || !in_options) - return 0; - - memset (&ds, 0, sizeof ds); - if (!evaluate_option_cache (&ds, packet, - lease, client_state, in_options, - cfg_options, scope, oc, file, line)) - return 0; + /* Only attempt to evaluate if option_cache is not null. This permits + * us to be called with option_lookup() as an argument. */ + 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)) { + /* 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 - * off, one is on, and 2 is 'ignore'. - */ - if (ds.len) { - result = ds.data [0]; - 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; + data_string_forget(&ds, MDL); + } + } + + return (result); } - /* Evaluate a boolean expression and return the result of the evaluation, or FALSE if it failed. */ diff --git a/includes/dhcpd.h b/includes/dhcpd.h index fed7b595..97b0951d 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -2010,7 +2010,8 @@ isc_result_t get_client_id(struct packet *, struct data_string *); void dhcpv6(struct packet *); /* bootp.c */ -void bootp (struct packet *); +void bootp(struct packet *); +void use_host_decl_name(struct packet *, struct lease* , struct option_state *); /* memory.c */ extern int (*group_write_hook) (struct group_object *); diff --git a/server/bootp.c b/server/bootp.c index d6dd96a2..7397cec1 100644 --- a/server/bootp.c +++ b/server/bootp.c @@ -180,21 +180,21 @@ void bootp (packet) /* Drop the request if it's not allowed for this client. */ if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) && - !evaluate_boolean_option_cache (&ignorep, packet, lease, - (struct client_state *)0, - packet -> options, options, - &lease -> scope, oc, MDL)) { + !evaluate_boolean_option_cache(&ignorep, packet, lease, + NULL, + packet->options, options, + &lease->scope, oc, MDL)) { if (!ignorep) log_info ("%s: bootp disallowed", msgbuf); goto out; } - if ((oc = lookup_option (&server_universe, + if ((oc = lookup_option(&server_universe, options, SV_ALLOW_BOOTING)) && - !evaluate_boolean_option_cache (&ignorep, packet, lease, - (struct client_state *)0, - packet -> options, options, - &lease -> scope, oc, MDL)) { + !evaluate_boolean_option_cache(&ignorep, packet, lease, + NULL, + packet->options, options, + &lease->scope, oc, MDL)) { if (!ignorep) log_info ("%s: booting disallowed", msgbuf); goto out; @@ -207,20 +207,26 @@ void bootp (packet) /* If we didn't get a known vendor magic number on the way in, just copy the input options to the output. */ - if (!packet -> options_valid && - !(evaluate_boolean_option_cache - (&ignorep, packet, lease, (struct client_state *)0, - packet -> options, options, &lease -> scope, - lookup_option (&server_universe, options, - SV_ALWAYS_REPLY_RFC1048), MDL))) { - memcpy (outgoing.raw -> options, - packet -> raw -> options, DHCP_MAX_OPTION_LEN); - outgoing.packet_length = BOOTP_MIN_LEN; + i = SV_ALWAYS_REPLY_RFC1048; + if (!packet->options_valid && + !(evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, + packet->options, options, + &lease->scope, + lookup_option (&server_universe, + options, i), MDL))) { + if (packet->packet_length > DHCP_FIXED_NON_UDP) { + 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 { /* Use the subnet mask from the subnet declaration if no other mask has been provided. */ - oc = (struct option_cache *)0; i = DHO_SUBNET_MASK; if (!lookup_option (&dhcp_universe, options, i)) { @@ -240,6 +246,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 can't pack options into the filename and server name buffers. */ diff --git a/server/dhcp.c b/server/dhcp.c index 08b67d74..0b0f6322 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -2732,33 +2732,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 use-host-decl-name flag is set. */ - i = DHO_HOST_NAME; - 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); - } - } + use_host_decl_name(packet, lease, state->options); /* If we don't have a hostname yet, and we've been asked to do a reverse lookup to find the hostname, do it. */ @@ -4538,3 +4515,43 @@ lowest_site_code(const void *key, unsigned len, void *object) return ISC_R_SUCCESS; } +/*! + * \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); + } + } +} |