From: Shawn Routhier Date: Thu, 11 Aug 2016 03:28:28 +0000 (-0700) Subject: [master] Include the raw data from a fully encapsualted option in the cache X-Git-Tag: v4_4_0b1_f1~145 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ee00c5b48cfe3920359e774a3b88245da58fb96;p=thirdparty%2Fdhcp.git [master] Include the raw data from a fully encapsualted option in the cache --- diff --git a/RELNOTES b/RELNOTES index 730a62561..3927402d6 100644 --- a/RELNOTES +++ b/RELNOTES @@ -54,6 +54,12 @@ by Eric Young (eay@cryptsoft.com). Changes since 4.3.0 (new features) +- Insert the raw data from a fully encapsualted option into the option cache. + This allows "exists" to check for the option if any sub options exist. It + also adds the raw data to the environment variables supplied to the client + script. + [ISC-Bugs #39863] + Changes since 4.3.0 (bug fixes) - Tidy up several small tickets. diff --git a/common/options.c b/common/options.c index b41ec4d49..223726ca0 100644 --- a/common/options.c +++ b/common/options.c @@ -187,80 +187,84 @@ int parse_option_buffer (options, buffer, length, universe) return 0; } - /* If the option contains an encapsulation, parse it. If - the parse fails, or the option isn't an encapsulation (by - far the most common case), or the option isn't entirely - an encapsulation, keep the raw data as well. */ - if (!(option && - (option->format[0] == 'e' || - option->format[0] == 'E') && - (parse_encapsulated_suboptions(options, option, - bp->data + offset, len, - universe, NULL)))) { - op = lookup_option(universe, options, code); - - if (op != NULL && universe->concat_duplicates) { - struct data_string new; - memset(&new, 0, sizeof new); - if (!buffer_allocate(&new.buffer, - op->data.len + len, - MDL)) { - log_error("parse_option_buffer: " - "No memory."); - buffer_dereference(&bp, MDL); - return 0; - } - /* Copy old option to new data object. */ - memcpy(new.buffer->data, op->data.data, - op->data.len); - /* Concat new option behind old. */ - memcpy(new.buffer->data + op->data.len, - bp->data + offset, len); - new.len = op->data.len + len; - new.data = new.buffer->data; - /* Save new concat'd object. */ - data_string_forget(&op->data, MDL); - data_string_copy(&op->data, &new, MDL); - data_string_forget(&new, MDL); - } else if (op != NULL) { - /* We must append this statement onto the - * end of the list. - */ - while (op->next != NULL) - op = op->next; - - if (!option_cache_allocate(&nop, MDL)) { - log_error("parse_option_buffer: " - "No memory."); - buffer_dereference(&bp, MDL); - return 0; - } - - option_reference(&nop->option, op->option, MDL); + /* If the option contains an encapsulation, parse it. In + any case keep the raw data as well. (Previous to 4.4.0 + we only kept the raw data if the parse failed, the option + wasn't an encapsulation (by far the most common case), or + the option wasn't entirely an encapsulation + */ + + if (option && + (option->format[0] == 'e' || option->format[0] == 'E')) { + (void) parse_encapsulated_suboptions(options, option, + bp->data + offset, + len, + universe, NULL); + } - nop->data.buffer = NULL; - buffer_reference(&nop->data.buffer, bp, MDL); - nop->data.data = bp->data + offset; - nop->data.len = len; + op = lookup_option(universe, options, code); + if (op == NULL) { + /* If we don't have an option create one */ + if (save_option_buffer(universe, options, bp, + bp->data + offset, len, + code, 1) == 0) { + log_error("parse_option_buffer: " + "save_option_buffer failed"); + buffer_dereference(&bp, MDL); + return (0); + } + } else if (universe->concat_duplicates) { + /* If we do have an option either concat with + what is there ...*/ + struct data_string new; + memset(&new, 0, sizeof new); + if (!buffer_allocate(&new.buffer, op->data.len + len, + MDL)) { + log_error("parse_option_buffer: No memory."); + buffer_dereference(&bp, MDL); + return (0); + } + /* Copy old option to new data object. */ + memcpy(new.buffer->data, op->data.data, + op->data.len); + /* Concat new option behind old. */ + memcpy(new.buffer->data + op->data.len, + bp->data + offset, len); + new.len = op->data.len + len; + new.data = new.buffer->data; + /* Save new concat'd object. */ + data_string_forget(&op->data, MDL); + data_string_copy(&op->data, &new, MDL); + data_string_forget(&new, MDL); + } else { + /* ... or we must append this statement onto the + * end of the list. + */ + while (op->next != NULL) + op = op->next; - option_cache_reference(&op->next, nop, MDL); - option_cache_dereference(&nop, MDL); - } else { - if (save_option_buffer(universe, options, bp, - bp->data + offset, len, - code, 1) == 0) { - log_error("parse_option_buffer: " - "save_option_buffer failed"); - buffer_dereference(&bp, MDL); - return 0; - } + if (!option_cache_allocate(&nop, MDL)) { + log_error("parse_option_buffer: No memory."); + buffer_dereference(&bp, MDL); + return (0); } + + option_reference(&nop->option, op->option, MDL); + + nop->data.buffer = NULL; + buffer_reference(&nop->data.buffer, bp, MDL); + nop->data.data = bp->data + offset; + nop->data.len = len; + + option_cache_reference(&op->next, nop, MDL); + option_cache_dereference(&nop, MDL); } + option_dereference(&option, MDL); offset += len; } buffer_dereference (&bp, MDL); - return 1; + return (1); } /* If an option in an option buffer turns out to be an encapsulation,