diff --git a/CHANGES b/CHANGES index e3513d1d29..594763bf98 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +2540. [func] Add a nibble mode to $GENERATE. [RT #18872] + 2539. [security] Update the interaction between recursion, allow-query, allow-query-cache and allow-recursion. [RT #19198] diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 9c241627c0..10c679c1d7 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -11476,20 +11476,30 @@ HOST-127.EXAMPLE. MX 0 . Available output forms are decimal (d), octal - (o) and hexadecimal + (o), hexadecimal (x or X - for uppercase). The default modifier is + for uppercase) and nibble + (n or N\ + for uppercase). The default modifier is ${0,0,d}. If the lhs is not absolute, the current $ORIGIN is appended to the name. - - For compatibility with earlier versions, $$ is still - recognized as indicating a literal $ in the output. - - - + + In nibble mode the value will be treated as + a if it was a reversed hexadecimal string + with each hexadecimal digit as a seperate + label. The width field includes the label + seperator. + + + For compatibility with earlier versions, + $$ is still recognized as + indicating a literal $ in the output. + + + ttl diff --git a/lib/dns/master.c b/lib/dns/master.c index 2518e210aa..dcd5955057 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.174 2009/01/17 23:47:42 tbox Exp $ */ +/* $Id: master.c,v 1.175 2009/01/30 04:35:44 marka Exp $ */ /*! \file */ @@ -618,6 +618,57 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, return (result); } +static const char *hex = "0123456789abcdef0123456789ABCDEF"; + +/*% + * Convert value into a nibble sequence from least significant to most + * significant nibble. Zero fill upper most significant nibbles if + * required to make the width. + * + * Returns the number of characters that should have been written without + * counting the terminating NUL. + */ +static unsigned int +nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) { + unsigned int count = 0; + + /* + * This reserve space for the NUL string terminator. + */ + if (length > 0) { + *numbuf = '\0'; + length--; + } + do { + char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)]; + value >>= 4; + if (length > 0) { + *numbuf++ = val; + *numbuf = '\0'; + length--; + } + if (width > 0) + width--; + count++; + /* + * If width is non zero then we need to add a label seperator. + * If value is non zero then we need to add another label and + * that requires a label seperator. + */ + if (width > 0 || value != 0) { + if (length > 0) { + *numbuf++ = '.'; + *numbuf = '\0'; + length--; + } + if (width > 0) + width--; + count++; + } + } while (value != 0 || width > 0); + return (count); +} + static isc_result_t genname(char *name, int it, char *buffer, size_t length) { char fmt[sizeof("%04000000000d")]; @@ -628,6 +679,7 @@ genname(char *name, int it, char *buffer, size_t length) { isc_textregion_t r; unsigned int n; unsigned int width; + isc_boolean_t nibblemode; r.base = buffer; r.length = length; @@ -642,10 +694,11 @@ genname(char *name, int it, char *buffer, size_t length) { isc_textregion_consume(&r, 1); continue; } + nibblemode = ISC_FALSE; strcpy(fmt, "%d"); /* Get format specifier. */ if (*name == '{' ) { - n = sscanf(name, "{%d,%u,%1[doxX]}", + n = sscanf(name, "{%d,%u,%1[doxXnN]}", &delta, &width, mode); switch (n) { case 1: @@ -655,6 +708,8 @@ genname(char *name, int it, char *buffer, size_t length) { "%%0%ud", width); break; case 3: + if (mode[0] == 'n' || mode[0] == 'N') + nibblemode = ISC_TRUE; n = snprintf(fmt, sizeof(fmt), "%%0%u%c", width, mode[0]); break; @@ -667,7 +722,12 @@ genname(char *name, int it, char *buffer, size_t length) { while (*name != '\0' && *name++ != '}') continue; } - n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta); + if (nibblemode) + n = nibbles(numbuf, sizeof(numbuf), width, + mode[0], it + delta); + else + n = snprintf(numbuf, sizeof(numbuf), fmt, + it + delta); if (n >= sizeof(numbuf)) return (ISC_R_NOSPACE); cp = numbuf;