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