From dba5803b955ada381d137b946f96cbb3604421ce Mon Sep 17 00:00:00 2001 From: David Hankins Date: Sat, 22 Jul 2006 02:24:16 +0000 Subject: [PATCH] - Support for compressed 'domain name list' style DHCP option contents, and in particular the domain search option (#119) was added. [ISC-Bugs #15934] --- RELNOTES | 6 + client/scripts/bsdos | 16 ++- client/scripts/freebsd | 40 ++++-- client/scripts/linux | 18 ++- client/scripts/netbsd | 14 ++- client/scripts/nextstep | 16 ++- client/scripts/openbsd | 16 ++- client/scripts/solaris | 16 ++- common/conflex.c | 10 +- common/dhcp-options.5 | 18 ++- common/options.c | 241 +++++++++++++++++++++++++++++++++---- common/parse.c | 69 ++++++++++- common/tables.c | 4 +- includes/dhcp.h | 1 + includes/dhcpd.h | 2 + includes/dhctoken.h | 3 +- includes/minires/minires.h | 9 +- 17 files changed, 431 insertions(+), 68 deletions(-) diff --git a/RELNOTES b/RELNOTES index f44dc64e4..dd1a95db1 100644 --- a/RELNOTES +++ b/RELNOTES @@ -143,6 +143,9 @@ and for prodding me into improving it. for a different name. In essence, this lets the client do as it will, ignoring this aspect of their request. +- Support for compressed 'domain name list' style DHCP option contents, and + in particular the domain search option (#119) was added. + Changes since 3.0.4 - A warning that host statements declared within subnet or shared-network @@ -208,6 +211,9 @@ and for prodding me into improving it. - Some manual pages were clarified pursuant to discussion on the dhcp-server mailing list. +- Support for compressed 'domain name list' style DHCP option contents, and + in particular the domain search option (#119) was added. + Changes since 3.0.4b2 - Null-termination sensing for certain clients that unfortunatley require diff --git a/client/scripts/bsdos b/client/scripts/bsdos index d076d92d0..fb0d43f22 100755 --- a/client/scripts/bsdos +++ b/client/scripts/bsdos @@ -1,11 +1,21 @@ #!/bin/sh make_resolv_conf() { - if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf + if [ x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + if [ "x$new_domain_search" != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ "x$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >> /etc/resolv.conf.dhclient done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf fi } diff --git a/client/scripts/freebsd b/client/scripts/freebsd index 2f0623efc..b40316eb1 100755 --- a/client/scripts/freebsd +++ b/client/scripts/freebsd @@ -1,6 +1,6 @@ #!/bin/sh # -# $Id: freebsd,v 1.16 2005/03/17 20:14:56 dhankins Exp $ +# $Id: freebsd,v 1.17 2006/07/22 02:24:16 dhankins Exp $ # # $FreeBSD$ @@ -12,24 +12,38 @@ fi make_resolv_conf() { if [ x"$new_domain_name_servers" != x ]; then - if [ "x$new_domain_name" != x ]; then - ( echo search $new_domain_name >/etc/resolv.conf ) - exit_status=$? + ( cat /dev/null > /etc/resolv.conf.dhclient ) + exit_status=$? + if [ $exit_status -ne 0 ]; then + $LOGGER "Unable to create /etc/resolv.conf.dhclient: Error $exit_status" else - if [ -e /etc/resolv.conf ] ; then - ( rm /etc/resolv.conf ) + if [ "x$new_domain_search" != x ]; then + ( echo search $new_domain_search >> /etc/resolv.conf.dhclient ) exit_status=$? - else - ( touch /etc/resolv.conf ) + elif [ "x$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + ( echo search $new_domain_name >> /etc/resolv.conf.dhclient ) exit_status=$? fi - fi - if [ $exit_status -ne 0 ]; then - $LOGGER "WARNING: Unable to update resolv.conf: Error $exit_status" - else for nameserver in $new_domain_name_servers; do - ( echo nameserver $nameserver >>/etc/resolv.conf ) + if [ $exit_status -ne 0 ]; then + break + fi + ( echo nameserver $nameserver >>/etc/resolv.conf.dhclient ) + exit_status=$? done + + # If there were no errors, attempt to mv the new file into place. + if [ $exit_status -eq 0 ]; then + ( mv /etc/resolv.conf.dhclient /etc/resolv.conf ) + exit_status = $? + fi + + if [ $exit_status -ne 0 ]; then + $LOGGER "Error while writing new /etc/resolv.conf." + fi fi fi } diff --git a/client/scripts/linux b/client/scripts/linux index 31ddd2fec..787efff25 100755 --- a/client/scripts/linux +++ b/client/scripts/linux @@ -23,12 +23,22 @@ # of the $1 in its args. make_resolv_conf() { - if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf - chmod 644 /etc/resolv.conf + if [ x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + chmod 644 /etc/resolv.conf.dhclient + if [ x"$new_domain_search" != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ x"$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >>/etc/resolv.conf.dhclient done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf fi } diff --git a/client/scripts/netbsd b/client/scripts/netbsd index d226cdff2..3de6b555d 100755 --- a/client/scripts/netbsd +++ b/client/scripts/netbsd @@ -2,10 +2,20 @@ make_resolv_conf() { if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf + cat /dev/null > /etc/resolv.conf.dhclient + if [ "x$new_domain_search != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ "x$new_domain_name != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >>/etc/resolv.conf.dhclient done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf fi } diff --git a/client/scripts/nextstep b/client/scripts/nextstep index 7600fb145..b80d175ad 100644 --- a/client/scripts/nextstep +++ b/client/scripts/nextstep @@ -31,11 +31,21 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ route add default $router 1 >/dev/null 2>&1 done fi - if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf + if [ x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + if [ "x$new_domain_search != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ "x$new_domain_name != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >>/etc/resolv.conf.dhclient done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf fi exit 0 fi diff --git a/client/scripts/openbsd b/client/scripts/openbsd index d076d92d0..64fead2e2 100644 --- a/client/scripts/openbsd +++ b/client/scripts/openbsd @@ -1,11 +1,21 @@ #!/bin/sh make_resolv_conf() { - if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf + if x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + if [ x"$new_domain_search" != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ x"$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >>/etc/resolv.conf.dhclient done + + mv /etc/ersolv.conf.dhclient /etc/resolv.conf fi } diff --git a/client/scripts/solaris b/client/scripts/solaris index e6187c715..c2403dc30 100755 --- a/client/scripts/solaris +++ b/client/scripts/solaris @@ -1,11 +1,21 @@ #!/bin/sh make_resolv_conf() { - if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then - echo search $new_domain_name >/etc/resolv.conf + if [ x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + if [ x"$new_domain_search" != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ x"$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf + echo nameserver $nameserver >>/etc/resolv.conf.dhclient done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf fi } diff --git a/common/conflex.c b/common/conflex.c index 33ffad542..7184a4aae 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: conflex.c,v 1.100 2006/06/16 19:26:44 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: conflex.c,v 1.101 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -655,8 +655,12 @@ static enum dhcp_token intern (atom, dfv) return DNS_DELETE; if (!strcasecmp (atom + 1, "omain")) return DOMAIN; - if (!strcasecmp (atom + 1, "omain-name")) - return DOMAIN_NAME; + if (!strncasecmp (atom + 1, "omain-", 6)) { + if (!strcasecmp(atom + 7, "name")) + return DOMAIN_NAME; + if (!strcasecmp(atom + 7, "list")) + return DOMAIN_LIST; + } if (!strcasecmp (atom + 1, "o-forward-update")) return DO_FORWARD_UPDATE; if (!strcasecmp (atom + 1, "ebug")) diff --git a/common/dhcp-options.5 b/common/dhcp-options.5 index ed2eaf052..923d624f9 100644 --- a/common/dhcp-options.5 +++ b/common/dhcp-options.5 @@ -1,4 +1,4 @@ -.\" $Id: dhcp-options.5,v 1.29 2006/06/01 20:23:17 dhankins Exp $ +.\" $Id: dhcp-options.5,v 1.30 2006/07/22 02:24:16 dhankins Exp $ .\" .\" Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC") .\" Copyright (c) 1996-2003 by Internet Software Consortium @@ -91,6 +91,13 @@ existing DHCP options. The domain name is stored just as if it were a text option. .PP The +.B domain-list +data type specifies a list of domain names, a space between each name and +the entire string enclosed in double quotes. These types of data are used +for the domain-search option for example, and encodes an RFC1035 compressed +DNS label list on the wire. +.PP +The .B flag data type specifies a boolean value. Booleans can be either true or false (or on or off, if that makes more sense to you). @@ -389,6 +396,15 @@ The domain-name-servers option specifies a list of Domain Name System should be listed in order of preference. .RE .PP +.B option \fBdomain-search\fR \fIstring\fR\fB;\fR +.RS 0.25i +.PP +The domain-search option specifies a 'search list' of Domain Names to be +used by the client to locate not-fully-qualified domain names. The difference +between this option and historic use of the domain-name option for the same +ends is that this option is encoded in RFC1035 compressed labels on the wire. +.RE +.PP .B option \fBextensions-path\fR \fItext\fR\fB;\fR .RS 0.25i .PP diff --git a/common/options.c b/common/options.c index 070cf71ca..0e0abfa5f 100644 --- a/common/options.c +++ b/common/options.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: options.c,v 1.91 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: options.c,v 1.92 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #define DHCP_OPTION_DATA @@ -46,6 +46,12 @@ struct option *vendor_cfg_option; static void do_option_set PROTO ((pair *, struct option_cache *, enum statement_op)); +static int pretty_escape(char **, char *, const unsigned char **, + const unsigned char *); +static int pretty_text(char **, char *, const unsigned char **, + const unsigned char *, int); +static int pretty_domain(char **, char *, const unsigned char **, + const unsigned char *); /* Parse all available options out of the specified packet. */ @@ -1146,6 +1152,7 @@ format_has_text(format) case 'a': case 'X': case 'x': + case 'D': return 0; /* 'E' is variable length, but not arbitrary...you @@ -1264,6 +1271,7 @@ format_min_length(format, oc) break; case 'd': /* "Domain name" */ + case 'D': /* "rfc1035 compressed names" */ case 't': /* "ASCII Text" */ case 'X': /* "ASCII or Hex Conditional */ case 'x': /* "Hex" */ @@ -1293,14 +1301,16 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) int emit_quotes; { static char optbuf [32768]; /* XXX */ + static char *endbuf = &optbuf[sizeof(optbuf)]; int hunksize = 0; int opthunk = 0; int hunkinc = 0; int numhunk = -1; int numelem = 0; + int count; + int i, j, k, l; char fmtbuf [32]; struct enumeration *enumbuf [32]; - int i, j, k, l; char *op = optbuf; const unsigned char *dp = data; struct in_addr foo; @@ -1439,32 +1449,73 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) for (j = 0; j < numelem; j++) { switch (fmtbuf [j]) { case 't': - if (emit_quotes) - *op++ = '"'; - for (; dp < data + len; dp++) { - if (!isascii (*dp) || - !isprint (*dp)) { - /* Skip trailing NUL. */ - if (dp + 1 != data + len || - *dp != 0) { - sprintf (op, "\\%03o", - *dp); - op += 4; - } - } else if (*dp == '"' || - *dp == '\'' || - *dp == '$' || - *dp == '`' || - *dp == '\\') { - *op++ = '\\'; - *op++ = *dp; - } else - *op++ = *dp; + /* endbuf-1 leaves room for NULL. */ + k = pretty_text(&op, endbuf - 1, &dp, + data + len, emit_quotes); + if (k == -1) { + log_error("Error printing text."); + break; } - if (emit_quotes) - *op++ = '"'; *op = 0; break; + case 'D': /* RFC1035 format name list */ + for( ; dp < (data + len) ; dp += k) { + unsigned char nbuff[NS_MAXCDNAME]; + const unsigned char *nbp, *nend; + + nend = &nbuff[sizeof(nbuff)]; + + /* If this is for ISC DHCP consumption + * (emit_quotes), lay it out as a list + * of STRING tokens. Otherwise, it is + * a space-separated list of DNS- + * escaped names as /etc/resolv.conf + * might digest. + */ + if (dp != data) { + if (op + 2 > endbuf) + break; + + if (emit_quotes) + *op++ = ','; + *op++ = ' '; + } + + k = MRns_name_unpack(data, + data + len, + dp, nbuff, + sizeof(nbuff)); + + if (k == -1) { + log_error("Invalid domain " + "list."); + break; + } + + /* If emit_quotes, then use ISC DHCP + * escapes. Otherwise, rely only on + * ns_name_ntop(). + */ + if (emit_quotes) { + nbp = nbuff; + pretty_domain(&op, endbuf-1, + &nbp, nend); + } else { + count = MRns_name_ntop( + nbuff, op, + (endbuf-op)-1); + + if (count == -1) { + log_error("Invalid " + "domain name."); + break; + } + + op += count; + } + } + *op = '\0'; + break; /* pretty-printing an array of enums is going to get ugly. */ case 'N': @@ -1478,7 +1529,6 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) break; } strcpy (op, enumbuf [j] -> values [i].name); - op += strlen (op); break; case 'I': foo.s_addr = htonl (getULong (dp)); @@ -2642,3 +2692,142 @@ void do_packet (interface, packet, len, from_port, from, hfrom) dump_rc_history (0); #endif } + +static int +pretty_escape(char **dst, char *dend, const unsigned char **src, + const unsigned char *send) +{ + int count = 0; + + /* If there aren't as many bytes left as there are in the source + * buffer, don't even bother entering the loop. + */ + if (dst == NULL || src == NULL || (*dst >= dend) || (*src > send) || + *dst == NULL || *src == NULL || + ((send - *src) > (dend - *dst))) + return -1; + + for ( ; *src < send ; *src++) { + if (!isascii (**src) || !isprint (**src)) { + /* Skip trailing NUL. */ + if ((*src + 1) != send || **src != '\0') { + if (*dst + 4 > dend) + return -1; + + sprintf(*dst, "\\%03o", + **src); + *dst += 4; + count += 4; + } + } else if (**src == '"' || **src == '\'' || **src == '$' || + **src == '`' || **src == '\\') { + if (*dst + 2 > dend) + return -1; + + **dst = '\\'; + *dst++; + **dst = **src; + *dst++; + count += 2; + } else { + if (*dst + 1 > dend) + return -1; + + **dst = **src; + *dst++; + count++; + } + } + + return count; +} + +static int +pretty_text(char **dst, char *dend, const unsigned char **src, + const unsigned char *send, int emit_quotes) +{ + int count; + + if (dst == NULL || dend == NULL || src == NULL || send == NULL || + *dst == NULL || *src == NULL || + ((*dst + (emit_quotes ? 2 : 0)) > dend) || (*src > send)) + return -1; + + if (emit_quotes) { + **dst = '"'; + *dst++; + } + + /* dend-1 leaves 1 byte for the closing quote. */ + count = pretty_escape(dst, dend - (emit_quotes ? 1 : 0), src, send); + + if (count == -1) + return -1; + + if (emit_quotes && (*dst < dend)) { + **dst = '"'; + *dst++; + + /* Includes quote prior to pretty_escape(); */ + count += 2; + } + + return count; +} + +static int +pretty_domain(char **dst, char *dend, const unsigned char **src, + const unsigned char *send) +{ + const unsigned char *tend; + int count = 2; + int tsiz, status; + + if (dst == NULL || dend == NULL || src == NULL || send == NULL || + *dst == NULL || *src == NULL || + ((*dst + 2) > dend) || (*src >= send)) + return -1; + + **dst = '"'; + *dst++; + + do { + /* Continue loop until end of src buffer. */ + if (*src >= send) + break; + + /* Consume tag size. */ + tsiz = **src; + *src++; + + /* At root, finis. */ + if (tsiz == 0) + break; + + tend = *src + tsiz; + + /* If the tag exceeds the source buffer, it's illegal. + * This should also trap compression pointers (which should + * not be in these buffers). + */ + if (tend > send) + return -1; + + /* dend-2 leaves room for a trailing dot and quote. */ + status = pretty_escape(dst, dend-2, src, tend); + + if ((status == -1) || ((*dst + 2) > dend)) + return -1; + + **dst = '.'; + *dst++; + count += status + 1; + } + while(1); + + **dst = '"'; + *dst++; + + return count; +} + diff --git a/common/parse.c b/common/parse.c index e1b6b772d..f146d2b11 100644 --- a/common/parse.c +++ b/common/parse.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: parse.c,v 1.112 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.113 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1391,6 +1391,9 @@ int parse_option_code_definition (cfile, option) case DOMAIN_NAME: type = 'd'; goto no_arrays; + case DOMAIN_LIST: + type = 'D'; + goto no_arrays; case TEXT: type = 't'; no_arrays: @@ -4704,7 +4707,18 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) } } break; - + + case 'D': /* Domain list... */ + t = parse_domain_list(cfile); + + if (!t) { + if ((*fmt)[1] != 'o') + skip_to_semi(cfile); + return 0; + } + + break; + case 'd': /* Domain name... */ val = parse_host_name (cfile); if (!val) { @@ -5188,3 +5202,54 @@ int parse_warn (struct parse *cfile, const char *fmt, ...) return 0; } + +struct expression * +parse_domain_list (cfile) + struct parse *cfile; +{ + const char *val; + enum dhcp_token token = SEMI; + struct expression *t = NULL; + unsigned len, clen = 0; + int result; + unsigned char compbuf[256 * NS_MAXCDNAME]; + const unsigned char *dnptrs[256], **lastdnptr; + + memset(compbuf, 0, sizeof(compbuf)); + memset(dnptrs, 0, sizeof(dnptrs)); + dnptrs[0] = compbuf; + lastdnptr = &dnptrs[255]; + + do { + /* Consume the COMMA token if peeked. */ + if (token == COMMA) + next_token(&val, NULL, cfile); + + /* Get next (or first) value. */ + token = next_token(&val, &len, cfile); + + if (token != STRING) { + parse_warn(cfile, "Expecting a domain string."); + return NULL; + } + + result = MRns_name_compress(val, compbuf + clen, + sizeof(compbuf) - clen, + dnptrs, lastdnptr); + + if (result < 0) { + parse_warn(cfile, "Error compressing domain list: %m"); + return NULL; + } + + clen += result; + + token = peek_token(&val, NULL, cfile); + } while (token == COMMA); + + if (!make_const_data(&t, compbuf, clen, 1, 1, MDL)) + log_fatal("No memory for domain list object."); + + return t; +} + diff --git a/common/tables.c b/common/tables.c index caad763d7..eefad58f3 100644 --- a/common/tables.c +++ b/common/tables.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: tables.c,v 1.55 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: tables.c,v 1.56 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -94,6 +94,7 @@ HASH_FUNCTIONS (option_code, const unsigned *, struct option, followed by a '.'. The width of the data is specified in the named enumeration. Named enumerations are tracked in parse.c. d - Domain name (i.e., FOO or FOO.BAR). + D - Domain list (i.e., example.com eng.example.com) */ struct universe dhcp_universe; @@ -185,6 +186,7 @@ static struct option dhcp_options[] = { { "nds-context", "t", &dhcp_universe, 87, 1 }, { "uap-servers", "t", &dhcp_universe, 98, 1 }, { "subnet-selection", "I", &dhcp_universe, 118, 1 }, + { "domain-search", "D", &dhcp_universe, 119, 1 }, { "vivco", "Evendor-class.", &dhcp_universe, 124, 1 }, { "vivso", "Evendor.", &dhcp_universe, 125, 1 }, { NULL, NULL, NULL, 0, 0 } diff --git a/includes/dhcp.h b/includes/dhcp.h index abdb85497..23b76fc18 100644 --- a/includes/dhcp.h +++ b/includes/dhcp.h @@ -149,6 +149,7 @@ struct dhcp_packet { #define DHO_FQDN 81 #define DHO_DHCP_AGENT_OPTIONS 82 #define DHO_SUBNET_SELECTION 118 /* RFC3011! */ +#define DHO_DOMAIN_SEARCH 119 /* RFC3397 */ #define DHO_VIVCO_SUBOPTIONS 124 #define DHO_VIVSO_SUBOPTIONS 125 /* The DHO_AUTHENTICATE option is not a standard yet, so I've diff --git a/includes/dhcpd.h b/includes/dhcpd.h index a0cc560b2..2f66d1c12 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -1384,6 +1384,8 @@ int parse_allow_deny PROTO ((struct option_cache **, struct parse *, int)); int parse_auth_key PROTO ((struct data_string *, struct parse *)); int parse_warn (struct parse *, const char *, ...) __attribute__((__format__(__printf__,2,3))); +struct expression *parse_domain_list (struct parse *cfile); + /* tree.c */ #if defined (NSUPDATE) diff --git a/includes/dhctoken.h b/includes/dhctoken.h index 5de431307..0315c7c9f 100644 --- a/includes/dhctoken.h +++ b/includes/dhctoken.h @@ -322,7 +322,8 @@ enum dhcp_token { MAX_LEASE_MISBALANCE = 626, MAX_LEASE_OWNERSHIP = 627, MAX_BALANCE = 628, - MIN_BALANCE = 629 + MIN_BALANCE = 629, + DOMAIN_LIST = 630 }; #define is_identifier(x) ((x) >= FIRST_TOKEN && \ diff --git a/includes/minires/minires.h b/includes/minires/minires.h index 19d213186..67c55cc72 100644 --- a/includes/minires/minires.h +++ b/includes/minires/minires.h @@ -45,6 +45,12 @@ isc_result_t minires_nupdate (res_state, ns_updrec *); int minires_ninit (res_state); ns_rcode isc_rcode_to_ns (isc_result_t); +int MRns_name_compress(const char *, u_char *, size_t, const unsigned char **, + const unsigned char **); +int MRns_name_unpack(const unsigned char *, const unsigned char *, + const unsigned char *, unsigned char *, size_t); +int MRns_name_ntop(const unsigned char *, char *, size_t); + #if defined (MINIRES_LIB) #define res_update minires_update #define res_mkupdate minires_mkupdate @@ -187,10 +193,7 @@ isc_result_t ns_sign_tcp_init (void *, const unsigned char *, unsigned, ns_tcp_tsig_state *); isc_result_t ns_sign_tcp (unsigned char *, unsigned *, unsigned, int, ns_tcp_tsig_state *, int); -int ns_name_ntop (const unsigned char *, char *, size_t); int ns_name_pton (const char *, unsigned char *, size_t); -int ns_name_unpack (const unsigned char *, const unsigned char *, - const unsigned char *, unsigned char *, size_t); int ns_name_pack (const unsigned char *, unsigned char *, unsigned, const unsigned char **, const unsigned char **); int ns_name_compress (const char *, unsigned char *, -- 2.39.5