summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2019-10-29 13:45:42 +0100
committerFrancis Dupont <fdupont@isc.org>2019-11-09 19:28:09 +0100
commiteb9885003bfa0058ce21b512199c2f9623464723 (patch)
tree5e350ecea8e5446181b9ddb30182b1357c4c690b
parentf17190e1b32daa6dddfa6f6584ccaac3c70330c5 (diff)
downloadisc-dhcp-eb9885003bfa0058ce21b512199c2f9623464723.tar.gz
Fixed output
-rw-r--r--common/ns_name.c35
-rw-r--r--common/options.c85
-rw-r--r--common/tests/Kyuafile1
-rw-r--r--common/tests/Makefile.am11
-rw-r--r--common/tests/Makefile.in9
-rw-r--r--common/tests/domain_name_test.c100
-rw-r--r--includes/ns_name.h3
7 files changed, 238 insertions, 6 deletions
diff --git a/common/ns_name.c b/common/ns_name.c
index be035f6f..f5198219 100644
--- a/common/ns_name.c
+++ b/common/ns_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -48,6 +48,39 @@ static int dn_find(const u_char *, const u_char *,
/* Public. */
/*
+ * MRns_name_len(eom, src)
+ * Compute the length of encoded uncompressed domain name.
+ * return:
+ * -1 if it fails, or to be consumed octets if it succeeds.
+ */
+int
+MRns_name_len(const u_char *eom, const u_char *src)
+{
+ const u_char *srcp;
+ unsigned n;
+ int len;
+
+ len = -1;
+ srcp = src;
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Limit checks. */
+ if (srcp + n >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += n;
+ }
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*
* MRns_name_ntop(src, dst, dstsiz)
* Convert an encoded domain name to printable ascii as per RFC1035.
* return:
diff --git a/common/options.c b/common/options.c
index eb05ec9e..405f7049 100644
--- a/common/options.c
+++ b/common/options.c
@@ -35,6 +35,8 @@ struct option *vendor_cfg_option;
static int pretty_text(char **, char *, const unsigned char **,
const unsigned char *, int);
+static int pretty_dname(char **, char *, const unsigned char *,
+ const unsigned char *);
static int pretty_domain(char **, char *, const unsigned char **,
const unsigned char *);
static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
@@ -1628,7 +1630,6 @@ format_has_text(format)
p = format;
while (*p != '\0') {
switch (*p++) {
- case 'd':
case 't':
return 1;
@@ -1642,6 +1643,7 @@ format_has_text(format)
case 'X':
case 'x':
case 'D':
+ case 'd':
return 0;
case 'c':
@@ -1884,8 +1886,23 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
numhunk = -2;
break;
case 'd':
- fmtbuf[l] = 't';
- /* Fall Through ! */
+ /* Should not be optional, array or compressed */
+ if ((option->format[i+1] == 'o') ||
+ (option->format[i+1] == 'a') ||
+ (option->format[i+1] == 'A') ||
+ (option->format[i+1] == 'c')) {
+ log_error("%s: Illegal use of domain name: %s",
+ option->name,
+ &(option->format[i-1]));
+ fmtbuf[l + 1] = 0;
+ }
+ k = MRns_name_len(data + len, data + hunksize);
+ if (k == -1) {
+ log_error("Invalid domain name.");
+ return "<error>";
+ }
+ hunksize += k;
+ break;
case 't':
fmtbuf[l + 1] = 0;
numhunk = -2;
@@ -2039,6 +2056,18 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
}
*op = 0;
break;
+ case 'd': /* RFC1035 format name */
+ k = MRns_name_len(data + len, dp);
+ /* Already tested... */
+ if (k == -1) {
+ log_error("invalid domain name.");
+ return "<error>";
+ }
+ pretty_dname(&op, endbuf-1, dp, data + len);
+ /* pretty_dname does not add the nul */
+ *op = '\0';
+ dp += k;
+ break;
case 'D': /* RFC1035 format name list */
for( ; dp < (data + len) ; dp += k) {
unsigned char nbuff[NS_MAXCDNAME];
@@ -4286,6 +4315,56 @@ pretty_text(char **dst, char *dend, const unsigned char **src,
}
static int
+pretty_dname(char **dst, char *dend, const unsigned char *src,
+ const unsigned char *send)
+{
+ const unsigned char *tend;
+ const unsigned char *srcp = src;
+ int count = 0;
+ int tsiz, status;
+
+ if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
+ *dst == NULL || ((*dst + 1) > dend) || (src >= send))
+ return -1;
+
+ do {
+ /* Continue loop until end of src buffer. */
+ if (srcp >= send)
+ break;
+
+ /* Consume tag size. */
+ tsiz = *srcp;
+ srcp++;
+
+ /* At root, finis. */
+ if (tsiz == 0)
+ break;
+
+ tend = srcp + 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-1 leaves room for a trailing dot and quote. */
+ status = pretty_escape(dst, dend-1, &srcp, tend);
+
+ if ((status == -1) || ((*dst + 1) > dend))
+ return -1;
+
+ **dst = '.';
+ (*dst)++;
+ count += status + 1;
+ }
+ while(1);
+
+ return count;
+}
+
+static int
pretty_domain(char **dst, char *dend, const unsigned char **src,
const unsigned char *send)
{
diff --git a/common/tests/Kyuafile b/common/tests/Kyuafile
index f3c352db..4952b549 100644
--- a/common/tests/Kyuafile
+++ b/common/tests/Kyuafile
@@ -3,6 +3,7 @@ test_suite('isc-dhcp')
atf_test_program{name='alloc_unittest'}
atf_test_program{name='dns_unittest'}
+atf_test_program{name='domain_name_unittest'}
atf_test_program{name='misc_unittest'}
atf_test_program{name='ns_name_unittest'}
atf_test_program{name='option_unittest'}
diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am
index 322f77e8..a5152653 100644
--- a/common/tests/Makefile.am
+++ b/common/tests/Makefile.am
@@ -9,7 +9,7 @@ ATF_TESTS =
if HAVE_ATF
ATF_TESTS += alloc_unittest dns_unittest misc_unittest ns_name_unittest \
- option_unittest
+ option_unittest domain_name_unittest
alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c
alloc_unittest_LDADD = $(ATF_LDFLAGS)
@@ -51,6 +51,15 @@ option_unittest_LDADD += ../libdhcp.@A@ ../../omapip/libomapi.@A@ \
@BINDLIBISCCFGDIR@/libisccfg.@A@ \
@BINDLIBISCDIR@/libisc.@A@
+domain_name_unittest_SOURCES = domain_name_test.c \
+ $(top_srcdir)/tests/t_api_dhcp.c
+domain_name_unittest_LDADD = $(ATF_LDFLAGS)
+domain_name_unittest_LDADD += ../libdhcp.@A@ ../../omapip/libomapi.@A@ \
+ @BINDLIBIRSDIR@/libirs.@A@ \
+ @BINDLIBDNSDIR@/libdns.@A@ \
+ @BINDLIBISCCFGDIR@/libisccfg.@A@ \
+ @BINDLIBISCDIR@/libisc.@A@
+
check: $(ATF_TESTS)
@if test $(top_srcdir) != ${top_builddir}; then \
cp $(top_srcdir)/common/tests/Atffile Atffile; \
diff --git a/common/tests/Makefile.in b/common/tests/Makefile.in
index 0fb4d408..b4ecc15c 100644
--- a/common/tests/Makefile.in
+++ b/common/tests/Makefile.in
@@ -416,6 +416,15 @@ ATF_TESTS = $(am__append_1)
@HAVE_ATF_TRUE@ @BINDLIBDNSDIR@/libdns.@A@ \
@HAVE_ATF_TRUE@ @BINDLIBISCCFGDIR@/libisccfg.@A@ \
@HAVE_ATF_TRUE@ @BINDLIBISCDIR@/libisc.@A@
+@HAVE_ATF_TRUE@domain_name_unittest_SOURCES = domain_name_test.c \
+@HAVE_ATF_TRUE@ $(top_srcdir)/tests/t_api_dhcp.c
+
+@HAVE_ATF_TRUE@domain_name_unittest_LDADD = $(ATF_LDFLAGS) \
+@HAVE_ATF_TRUE@ ../libdhcp.@A@ ../../omapip/libomapi.@A@ \
+@HAVE_ATF_TRUE@ @BINDLIBIRSDIR@/libirs.@A@ \
+@HAVE_ATF_TRUE@ @BINDLIBDNSDIR@/libdns.@A@ \
+@HAVE_ATF_TRUE@ @BINDLIBISCCFGDIR@/libisccfg.@A@ \
+@HAVE_ATF_TRUE@ @BINDLIBISCDIR@/libisc.@A@
all: all-recursive
.SUFFIXES:
diff --git a/common/tests/domain_name_test.c b/common/tests/domain_name_test.c
new file mode 100644
index 00000000..8bd70aa2
--- /dev/null
+++ b/common/tests/domain_name_test.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+#include <atf-c.h>
+#include "dhcpd.h"
+
+ATF_TC(pretty_print_domain_name);
+
+ATF_TC_HEAD(pretty_print_domain_name, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Verify pretty_print_option can render a domain name.");
+}
+
+/*
+ * This test verifies that pretty_print_option() correctly render a
+ * domain name.
+ *
+ */
+ATF_TC_BODY(pretty_print_domain_name, tc)
+{
+ struct option *option;
+ unsigned code;
+ unsigned char good_data[] =
+ { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00 };
+ unsigned char short_data[] =
+ { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d };
+ unsigned char long_data[] =
+ { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00,
+ 0x01, 0x02 };
+ const char *output_buf;
+
+ initialize_common_option_spaces();
+
+ /* We'll use v4-lost because it happens to be format d */
+ code = 137;
+ option = NULL;
+ if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
+ &code, 0, MDL)) {
+ atf_tc_fail("can't find option %d", code);
+ }
+
+ if (option == NULL) {
+ atf_tc_fail("option is NULL");
+ }
+
+ /* First we will try a good value we know should fit. */
+ output_buf = pretty_print_option(option, good_data, sizeof(good_data), 0,
+ 0);
+
+ /* Make sure we get what we expect */
+ if (!output_buf || strcmp(output_buf, "booya.com.")) {
+ atf_tc_fail("pretty_print_option did not return 'booya.com.'");
+ }
+
+ fprintf(stderr, "good!\n");
+
+ /* Now we'll try a data value that's too short */
+ output_buf = pretty_print_option(option, short_data, sizeof(short_data),
+ 0, 0);
+
+ /* Make sure we safely get an error */
+ if (!output_buf || strcmp(output_buf, "<error>")) {
+ atf_tc_fail("pretty_print_option did not return \"<error>\"");
+ }
+
+ /* Now we'll try a data value that's too large */
+ output_buf = pretty_print_option(option, long_data, sizeof(long_data), 0,
+ 0);
+
+ /* This logs but does not return an error */
+ if (!output_buf || strcmp(output_buf, "booya.com.")) {
+ atf_tc_fail("pretty_print_option did not return 'booya.com.' (large)");
+ }
+}
+
+
+/* This macro defines main() method that will call specified
+ test cases. tp and simple_test_case names can be whatever you want
+ as long as it is a valid variable identifier. */
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, pretty_print_domain_name);
+
+ return (atf_no_error());
+}
diff --git a/includes/ns_name.h b/includes/ns_name.h
index 5095c1ce..a2c42769 100644
--- a/includes/ns_name.h
+++ b/includes/ns_name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2001-2003 by Internet Software Consortium
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -31,6 +31,7 @@
* <viraj_bais@ccm.fm.intel.com>
*/
+int MRns_name_len(const unsigned char *, const unsigned char *);
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 *,