mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 01:49:35 +00:00
- Support for compressed 'domain name list' style DHCP option contents, and
in particular the domain search option (#119) was added. [ISC-Bugs #15934]
This commit is contained in:
parent
8f4c32a101
commit
dba5803b95
6
RELNOTES
6
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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
|
241
common/options.c
241
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 && \
|
||||
|
@ -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 *,
|
||||
|
Loading…
x
Reference in New Issue
Block a user