UNREACHABLE();
}
- sa = *(cfg_obj_assockaddr(obj));
- INSIST(isc_sockaddr_pf(&sa) == af);
- INSIST(isc_sockaddr_getport(&sa) == 0);
+ if (cfg_obj_isvoid(obj)) {
+ /*
+ * We don't want to use this address family, let's
+ * bail now. The dispatch object for this family will
+ * be null then not used to run queries.
+ */
+ return ISC_R_SUCCESS;
+ } else {
+ /*
+ * obj _has_ to be sockaddr here, cfg_obj_assockaddr()
+ * asserts this internally.
+ */
+ sa = *(cfg_obj_assockaddr(obj));
+ INSIST(isc_sockaddr_pf(&sa) == af);
+ INSIST(isc_sockaddr_getport(&sa) == 0);
+ }
/*
* If we don't support this address family, we're done!
(void)cfg_map_get(cpeer, "query-source-v6", &obj);
}
if (obj != NULL) {
+ INSIST(cfg_obj_issockaddr(obj));
result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj));
if (result != ISC_R_SUCCESS) {
goto cleanup;
proxy \
pipelined \
qmin \
+ query-source \
reclimit \
redirect \
resolver \
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source none;
+ query-source-v6 none;
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+server 1.2.3.4 {
+ query-source none;
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+server fd92:7065:b8e:ffff::1 {
+ query-source-v6 none;
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source none;
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source-v6 none;
+};
*/
server 1.2.3.4 {
- query-source address 10.10.10.10;
+ query-source 10.10.10.10;
};
*/
server fd92:7065:b8e:ffff::1 {
- query-source-v6 address fd92:7065:b8e:ffff::2;
+ query-source-v6 fd92:7065:b8e:ffff::2;
};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ listen-on { 10.53.0.1; };
+ recursion no;
+ dnssec-validation no;
+ query-source 10.53.0.1;
+ query-source-v6 fd92:7065:b8e:ffff::1;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 300 SOA . . 0 0 0 0 0
+. 300 NS a.root-servers.nil.
+a.root-servers.nil. 300 A 10.53.0.1
+example. 300 A 10.53.0.10
+exampletwo. 300 A 10.53.0.11
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion yes;
+ dnssec-validation no;
+ query-source none;
+ query-source-v6 fd92:7065:b8e:ffff::2;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ recursion yes;
+ dnssec-validation no;
+ query-source-v6 none;
+ query-source 10.53.0.3;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { fd92:7065:b8e:ffff::4; };
+ recursion yes;
+ dnssec-validation no;
+ query-source none;
+ query-source-v6 fd92:7065:b8e:ffff::4;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { fd92:7065:b8e:ffff::5; };
+ recursion yes;
+ dnssec-validation no;
+ query-source 10.53.0.5;
+ query-source-v6 none;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# 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 https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
--- /dev/null
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# 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 https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest
+import isctest
+
+pytest.importorskip("dns")
+import dns.message
+
+pytestmark = pytest.mark.extra_artifacts(
+ [
+ "ns*/named.pid",
+ "ns*/managed-keys.bind*",
+ ]
+)
+
+
+def test_querysource_none():
+ msg = dns.message.make_query("example.", "A", want_dnssec=False)
+
+ res = isctest.query.udp(msg, "10.53.0.2")
+ isctest.check.noerror(res)
+
+ res = isctest.query.udp(msg, "10.53.0.3")
+ isctest.check.noerror(res)
+
+ res = isctest.query.udp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ res = isctest.query.udp(msg, "10.53.0.5")
+ isctest.check.servfail(res)
+
+ # using a different name below to make sure we don't use the
+ # resolver cache
+
+ msg = dns.message.make_query("exampletwo.", "A", want_dnssec=False)
+
+ res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::2")
+ isctest.check.noerror(res)
+
+ res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::3")
+ isctest.check.noerror(res)
+
+ res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::4")
+ isctest.check.servfail(res)
+
+ res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::5")
+ isctest.check.servfail(res)
.. namedconf:statement:: query-source
:tags: query
- :short: Controls the IPv4 address from which queries are issued.
+ :short: Controls the IPv4 address from which queries are issued. If
+ `none`, then no IPv4 address would be used to issue the
+ query and therefore only IPv6 servers are queried.
.. namedconf:statement:: query-source-v6
:tags: query
- :short: Controls the IPv6 address from which queries are issued.
+ :short: Controls the IPv6 address from which queries are issued. If
+ `none`, then no IPv6 address would be used to issue the
+ query and therefore only IPv4 servers are quried.
If the server does not know the answer to a question, it queries other
name servers. :any:`query-source` specifies the address used for
prefetch <integer> [ <integer> ];
provide-ixfr <boolean>;
qname-minimization ( strict | relaxed | disabled | off );
- query-source [ address ] ( <ipv4_address> | * );
- query-source-v6 [ address ] ( <ipv6_address> | * );
+ query-source [ address ] ( <ipv4_address> | * | none );
+ query-source-v6 [ address ] ( <ipv6_address> | * | none );
querylog <boolean>;
rate-limit {
all-per-second <integer>;
prefetch <integer> [ <integer> ];
provide-ixfr <boolean>;
qname-minimization ( strict | relaxed | disabled | off );
- query-source [ address ] ( <ipv4_address> | * );
- query-source-v6 [ address ] ( <ipv6_address> | * );
+ query-source [ address ] ( <ipv4_address> | * | none );
+ query-source-v6 [ address ] ( <ipv6_address> | * | none );
rate-limit {
all-per-second <integer>;
errors-per-second <integer>;
* Warn if query-source or query-source-v6 options specify
* a port, and fail if they specify the DNS port.
*/
+ unsigned int none_found = false;
+
for (i = 0; i < ARRAY_SIZE(sources); i++) {
obj = NULL;
(void)cfg_map_get(options, sources[i], &obj);
- if (obj != NULL) {
- const isc_sockaddr_t *sa =
- cfg_obj_assockaddr(obj);
- in_port_t port = isc_sockaddr_getport(sa);
- if (port == dnsport) {
+ if (obj != NULL && cfg_obj_isvoid(obj)) {
+ none_found++;
+
+ if (none_found > 1) {
cfg_obj_log(obj, ISC_LOG_ERROR,
- "'%s' cannot specify the "
- "DNS listener port (%d)",
- sources[i], port);
+ "query-source and "
+ "query-source-v6 can't be "
+ "none at the same time.");
result = ISC_R_FAILURE;
- } else if (port != 0) {
- cfg_obj_log(obj, ISC_LOG_WARNING,
- "'%s': specifying a port "
- "is not recommended",
- sources[i]);
+ break;
}
}
}
}
(void)cfg_map_get(v1, xfr, &obj);
if (obj != NULL) {
- const isc_sockaddr_t *sa =
- cfg_obj_assockaddr(obj);
- in_port_t port = isc_sockaddr_getport(sa);
- if (port == dnsport) {
+ if (cfg_obj_issockaddr(obj)) {
+ const isc_sockaddr_t *sa =
+ cfg_obj_assockaddr(obj);
+ in_port_t port =
+ isc_sockaddr_getport(sa);
+ if (port == dnsport) {
+ cfg_obj_log(obj, ISC_LOG_ERROR,
+ "'%s' cannot "
+ "specify the "
+ "DNS listener port "
+ "(%d)",
+ xfr, port);
+ result = ISC_R_FAILURE;
+ }
+ } else {
cfg_obj_log(obj, ISC_LOG_ERROR,
- "'%s' cannot specify the "
- "DNS listener port (%d)",
- xfr, port);
+ "'none' is not a legal "
+ "'%s' parameter in a "
+ "server block",
+ xfr);
result = ISC_R_FAILURE;
}
}
static cfg_type_t cfg_type_qminmethod;
static cfg_type_t cfg_type_querysource4;
static cfg_type_t cfg_type_querysource6;
+static cfg_type_t cfg_type_server_querysource4;
+static cfg_type_t cfg_type_server_querysource6;
static cfg_type_t cfg_type_querysource;
static cfg_type_t cfg_type_server;
static cfg_type_t cfg_type_server_key_kludge;
{ "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
{ "padding", &cfg_type_uint32, 0 },
{ "provide-ixfr", &cfg_type_boolean, 0 },
- { "query-source", &cfg_type_querysource4, 0 },
- { "query-source-v6", &cfg_type_querysource6, 0 },
+ { "query-source", &cfg_type_server_querysource4, 0 },
+ { "query-source-v6", &cfg_type_server_querysource6, 0 },
{ "request-expire", &cfg_type_boolean, 0 },
{ "request-ixfr", &cfg_type_boolean, 0 },
{ "request-ixfr-max-diffs", &cfg_type_uint32, 0 },
static isc_result_t
parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+
REQUIRE(type != NULL);
+ CHECK(cfg_peektoken(pctx, 0));
- isc_result_t result = cfg_parse_sockaddr_generic(
- pctx, &cfg_type_querysource, type, ret);
- /* Preserve legacy query-source logging. */
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "address") == 0)
+ {
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_peektoken(pctx, 0));
+ }
+
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "none") == 0)
+ {
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_create_obj(pctx, &cfg_type_none, ret));
+ } else {
+ CHECK(cfg_parse_sockaddr_generic(pctx, &cfg_type_querysource,
+ type, ret));
+ }
+
+cleanup:
if (result != ISC_R_SUCCESS) {
cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid query source");
}
+
return result;
}
print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) {
isc_netaddr_t na;
isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr);
- cfg_print_cstr(pctx, "address ");
cfg_print_rawaddr(pctx, &na);
}
static void
-doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) {
+doc__querysource(cfg_printer_t *pctx, const cfg_type_t *type, bool has_none) {
const unsigned int *flagp = type->of;
cfg_print_cstr(pctx, "[ address ] ( ");
+
if ((*flagp & CFG_ADDR_V4OK) != 0) {
cfg_print_cstr(pctx, "<ipv4_address>");
} else if ((*flagp & CFG_ADDR_V6OK) != 0) {
} else {
UNREACHABLE();
}
- cfg_print_cstr(pctx, " | * )");
+
+ cfg_print_cstr(pctx, " | *");
+ if (has_none) {
+ cfg_print_cstr(pctx, " | none");
+ }
+ cfg_print_cstr(pctx, " )");
+}
+
+static void
+doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) {
+ doc__querysource(pctx, type, true);
+}
+
+static void
+doc_serverquerysource(cfg_printer_t *pctx, const cfg_type_t *type) {
+ doc__querysource(pctx, type, false);
}
static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK;
NULL, &querysource6wild_flags
};
+static cfg_type_t cfg_type_server_querysource4 = {
+ "querysource4", parse_querysource, NULL, doc_serverquerysource,
+ NULL, &querysource4wild_flags
+};
+
+static cfg_type_t cfg_type_server_querysource6 = {
+ "querysource6", parse_querysource, NULL, doc_serverquerysource,
+ NULL, &querysource6wild_flags
+};
+
static cfg_type_t cfg_type_querysource = { "querysource", NULL,
print_querysource, NULL,
&cfg_rep_sockaddr, NULL };
check_PROGRAMS = \
duration_test \
- parser_test
+ parser_test \
+ grammar_test
include $(top_srcdir)/Makefile.tests
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <sched.h> /* IWYU pragma: keep */
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define UNIT_TESTING
+#include <cmocka.h>
+
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <tests/isc.h>
+
+static void
+write_to_buffer(void *closure, const char *text, int textlen);
+
+static isc_buffer_t gbuffer;
+static char gtext[512];
+static cfg_printer_t gprinter = {
+ .f = write_to_buffer, .closure = &gbuffer, .indent = 0, .flags = 0
+};
+
+ISC_SETUP_TEST_IMPL(group) {
+ isc_buffer_init(&gbuffer, gtext, sizeof(gtext));
+ isc_logconfig_t *logconfig = isc_logconfig_get();
+ isc_log_createandusechannel(
+ logconfig, "default_stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, ISC_LOGDESTINATION_STDERR, 0,
+ ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_DEFAULT);
+
+ return 0;
+}
+
+static void
+write_to_buffer(void *closure, const char *text, int textlen) {
+ isc_buffer_putmem((isc_buffer_t *)closure, (const unsigned char *)text,
+ textlen);
+}
+
+static void
+assert_text(const char *text) {
+ assert_int_equal(strcasecmp(text, isc_buffer_base(&gbuffer)), 0);
+ isc_buffer_clear(&gbuffer);
+ memset(gtext, 0, sizeof(gtext));
+}
+
+static const cfg_clausedef_t *
+find_clause(const cfg_type_t *map, const char *name) {
+ const char *found_name = NULL;
+ const void *clauses = NULL;
+ unsigned int idx;
+
+ found_name = cfg_map_firstclause(map, &clauses, &idx);
+ while (name != NULL && strcasecmp(name, found_name)) {
+ found_name = cfg_map_nextclause(map, &clauses, &idx);
+ }
+
+ return ((cfg_clausedef_t *)clauses) + idx;
+}
+
+static void
+test__querysource(const char *clause_name, const char *name,
+ const char *expected) {
+ const cfg_clausedef_t *options_clause = NULL;
+ options_clause = find_clause(&cfg_type_namedconf, clause_name);
+ assert_non_null(options_clause);
+
+ const cfg_clausedef_t *querysource_clause = NULL;
+ querysource_clause = find_clause(options_clause->type, name);
+ assert_non_null(querysource_clause);
+ querysource_clause->type->doc(&gprinter, querysource_clause->type);
+ assert_text(expected);
+}
+
+ISC_RUN_TEST_IMPL(query_source) {
+ test__querysource("options", "query-source",
+ "[ address ] ( <ipv4_address> | * | none )");
+}
+
+ISC_RUN_TEST_IMPL(query_source_v6) {
+ test__querysource("options", "query-source-v6",
+ "[ address ] ( <ipv6_address> | * | none )");
+}
+
+ISC_RUN_TEST_IMPL(server_query_source) {
+ test__querysource("server", "query-source",
+ "[ address ] ( <ipv4_address> | * )");
+}
+
+ISC_RUN_TEST_IMPL(server_query_source_v6) {
+ test__querysource("server", "query-source-v6",
+ "[ address ] ( <ipv6_address> | * )");
+}
+
+static void
+test__query_source_print(const char *config, const char *expected) {
+ isc_result_t result;
+ isc_buffer_t buffer;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *output_conf = NULL;
+
+ result = cfg_parser_create(mctx, &parser);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ isc_buffer_constinit(&buffer, config, strlen(config));
+ isc_buffer_add(&buffer, strlen(config));
+
+ result = cfg_parse_buffer(parser, &buffer, "text1", 0,
+ &cfg_type_namedconf, 0, &output_conf);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ assert_non_null(output_conf);
+
+ cfg_printer_t pctx = gprinter;
+ pctx.flags = CFG_PRINTER_ONELINE;
+
+ output_conf->type->print(&pctx, output_conf);
+ assert_text(expected);
+
+ cfg_obj_destroy(parser, &output_conf);
+ cfg_parser_reset(parser);
+ cfg_parser_destroy(&parser);
+}
+
+ISC_RUN_TEST_IMPL(query_source_print_none) {
+ test__query_source_print(" options { query-source none; };",
+ "options { query-source none; }; ");
+ test__query_source_print(
+ " options { query-source address none; };",
+ "options { query-source none; }; ");
+ test__query_source_print(" options {query-source-v6 none; };",
+ "options { query-source-v6 none; }; ");
+ test__query_source_print(" options {query-source-v6 address none; };",
+ "options { query-source-v6 none; }; ");
+}
+
+ISC_RUN_TEST_IMPL(query_source_print_addr) {
+ test__query_source_print(" options{query-source address 127.0.0.1;};",
+ "options { query-source 127.0.0.1; }; ");
+ test__query_source_print(" options{query-source 127.0.0.1;};",
+ "options { query-source 127.0.0.1; }; ");
+ test__query_source_print(" options{query-source-v6 address ::1; };",
+ "options { query-source-v6 ::1; }; ");
+ test__query_source_print(" options{query-source-v6 ::1; };",
+ "options { query-source-v6 ::1; }; ");
+}
+
+ISC_TEST_LIST_START
+
+ISC_TEST_ENTRY(query_source)
+ISC_TEST_ENTRY(query_source_v6)
+ISC_TEST_ENTRY(server_query_source)
+ISC_TEST_ENTRY(server_query_source_v6)
+ISC_TEST_ENTRY(query_source_print_none)
+ISC_TEST_ENTRY(query_source_print_addr)
+
+ISC_TEST_LIST_END
+
+ISC_TEST_MAIN_CUSTOM(setup_test_group, NULL)