rpms/dhcp/devel dhcp-3.0.3-trailing_nul_options_2.patch,NONE,1.1
fedora-cvs-commits at redhat.com
fedora-cvs-commits at redhat.com
Fri Nov 18 20:39:06 UTC 2005
Author: jvdias
Update of /cvs/dist/rpms/dhcp/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv16595
Added Files:
dhcp-3.0.3-trailing_nul_options_2.patch
Log Message:
apply upstream improvements to trailing nul options bz160655 patch
dhcp-3.0.3-trailing_nul_options_2.patch:
options.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 177 insertions(+), 12 deletions(-)
--- NEW FILE dhcp-3.0.3-trailing_nul_options_2.patch ---
--- dhcp-3.0.3/common/options.c.trailing_nul_options_2 2005-11-18 15:31:34.000000000 -0500
+++ dhcp-3.0.3/common/options.c 2005-11-18 15:33:01.000000000 -0500
@@ -1042,6 +1042,169 @@
return bufix;
}
+/* Return true if the format string has a variable length text option
+ * ("t"), return false otherwise.
+ */
+
+int
+format_has_text(format)
+ const char *format;
+{
+ const char *p;
+/* int retval = 0; */
+
+ p = format;
+ while (*p != '\0') {
+ switch (*p++) {
+ case 'd':
+ case 't':
+ return 1;
+
+ /* These symbols are arbitrary, not fixed or
+ * determinable length...text options with them is
+ * invalid.
+ */
+ case 'A':
+ case 'a':
+ case 'X':
+ case 'x':
+ return 0;
+
+ /* 'E' is variable length, but not arbitrary...you
+ * can find its length if you can find an END option.
+ * N is one-byte in length but trails a name of a
+ * space defining the enumeration values. So treat
+ * both the same - valid, fixed-length fields.
+ */
+ case 'E':
+ case 'N':
+ /* Consume the space name. */
+ while ((*p != '\0') && (*p++ != '.'))
+ ;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Determine the minimum length of a DHCP option prior to any variable
+ * or inconsistent length formats, according to its configured format
+ * variable (and possibly from supplied option cache contents for variable
+ * length format symbols).
+ */
+
+int
+format_min_length(format, oc)
+ const char *format;
+ struct option_cache *oc;
+{
+ const char *p;
+ int min_len = 0;
+ int last_size = 0;
+
+ p = format;
+ while (*p != '\0') {
+ switch (*p++) {
+ case 'I': /* IPv4 Address */
+ case 'l': /* int32_t */
+ case 'L': /* uint32_t */
+ case 'T': /* Lease Time, uint32_t equivalent */
+ min_len += 4;
+ last_size = 4;
+ break;
+
+ case 's': /* int16_t */
+ case 'S': /* uint16_t */
+ min_len += 2;
+ last_size = 2;
+ break;
+
+ case 'N': /* Enumeration in 1-byte values. */
+ /* Consume space name. */
+ while ((*p != '\0') && (*p++ != '.'))
+ ;
+
+ /* Fall Through to handle as one-byte field */
+
+ case 'b': /* int8_t */
+ case 'B': /* uint8_t */
+ case 'F': /* Flag that is always true. */
+ case 'f': /* Flag */
+ min_len++;
+ last_size = 1;
+ break;
+
+ case 'o': /* Last argument is optional. */
+ min_len -= last_size;
+ case 'e': /* Encapsulation hint (there is an 'E' later). */
+ last_size = 0;
+ break;
+
+ case 'E': /* Encapsulated options. */
+ /* Consume space name. */
+ while ((*p != '\0') && (*p++ != '.'))
+ ;
+
+ /* Find an end option, or find that the encaps options
+ * go all the way to the end (or beyond) of the data
+ * portion of the option.
+ */
+ last_size = 0;
+ while (min_len < oc->data.len) {
+ if (oc->data.data[min_len] == DHO_END) {
+ min_len++;
+ last_size++;
+ break;
+ } else if (oc->data.data[min_len] == DHO_PAD) {
+ min_len++;
+ last_size++;
+ } else if ((min_len + 1) < oc->data.len) {
+ min_len += oc->data.data[min_len+1]+2;
+ last_size += oc->data.data[min_len+1]+2;
+ } else {
+ /* Suboption length is out of bounds,
+ * advance beyond the code/length pair
+ * to trigger below error conditonal.
+ */
+ min_len += 2;
+ last_size += 2;
+ break;
+ }
+ }
+
+ if (min_len > oc->data.len) {
+ log_error("format_min_length(%s): "
+ "Encapsulated options exceed "
+ "supplied buffer.", format);
+ return INT_MAX;
+ }
+
+ break;
+
+ case 'd': /* "Domain name" */
+ case 't': /* "ASCII Text" */
+ case 'X': /* "ASCII or Hex Conditional */
+ case 'x': /* "Hex" */
+ case 'A': /* Array of all that precedes. */
+ case 'a': /* Array of preceding symbol. */
+ return min_len;
+
+ default:
+ /* No safe value is known. */
+ log_error("format_min_length(%s): No safe value "
+ "for unknown format symbols.", format);
+ return INT_MAX;
+ }
+ }
+
+ return min_len;
+}
+
+
/* Format the specified option so that a human can easily read it. */
const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
@@ -1453,7 +1616,6 @@
{
struct buffer *lbp = (struct buffer *)0;
struct option_cache *op = (struct option_cache *)0;
- int formlen=0;
if (!option_cache_allocate (&op, MDL)) {
log_error ("No memory for option %s.%s.",
@@ -1497,17 +1659,20 @@
op -> option = option;
- /* If the option format ends in a "t" field, trailing NULLs are
- * considered invalid, to be removed (RFC2132 Section 2).
- */
- formlen = strlen(option->format);
- if ((formlen > 0) && (option->format[formlen-1] == 't')) {
- while (op->data.len &&
- (op->data.data[op->data.len-1] == '\0')) {
- op->data.len--;
- op->flags |= OPTION_HAD_NULLS;
- }
- }
+ /* If this option is ultimately a text option, null determinate to
+ * comply with RFC2132 section 2. Mark a flag so this can be sensed
+ * later to echo NULLs back to clients that supplied them (they
+ * probably expect them).
+ */
+ if (format_has_text(option->format)) {
+ int min_len = format_min_length(option->format, op);
+
+ while ((op->data.len > min_len) &&
+ (op->data.data[op->data.len-1] == '\0')) {
+ op->data.len--;
+ op->flags |= OPTION_HAD_NULLS;
+ }
+ }
/* Now store the option. */
save_option (universe, options, op);
More information about the fedora-cvs-commits
mailing list