diff --git a/CHANGES b/CHANGES
index a45d476b46..ff1982dc76 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4691. [func] Add -4/-6 command line options to nsupdate and rndc.
+ [RT #45632]
+
4690. [bug] Command line options -4/-6 were handled inconsistently
between tools. [RT #45632]
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
index 70d7a55277..06e536622b 100644
--- a/bin/nsupdate/nsupdate.c
+++ b/bin/nsupdate/nsupdate.c
@@ -850,7 +850,7 @@ setup_system(void) {
isc_result_t result;
isc_sockaddr_t bind_any, bind_any6;
lwres_result_t lwresult;
- unsigned int attrs, attrmask;
+ unsigned int attrs, attrmask, flags;
int i;
isc_logconfig_t *logconfig = NULL;
@@ -858,17 +858,6 @@ setup_system(void) {
dns_result_register();
- result = isc_net_probeipv4();
- if (result == ISC_R_SUCCESS)
- have_ipv4 = ISC_TRUE;
-
- result = isc_net_probeipv6();
- if (result == ISC_R_SUCCESS)
- have_ipv6 = ISC_TRUE;
-
- if (!have_ipv4 && !have_ipv6)
- fatal("could not find either IPv4 or IPv6");
-
result = isc_log_create(gmctx, &glctx, &logconfig);
check_result(result, "isc_log_create");
@@ -881,7 +870,16 @@ setup_system(void) {
isc_log_setdebuglevel(glctx, logdebuglevel);
- lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free, 1);
+ flags = LWRES_CONTEXT_SERVERMODE;
+ if (have_ipv4) {
+ flags |= LWRES_CONTEXT_USEIPV4;
+ }
+ if (have_ipv6) {
+ flags |= LWRES_CONTEXT_USEIPV6;
+ }
+
+ lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free,
+ flags);
if (lwresult != LWRES_R_SUCCESS)
fatal("lwres_context_create failed");
@@ -909,15 +907,15 @@ setup_system(void) {
if (servers == NULL)
fatal("out of memory");
- if (have_ipv4) {
- in.s_addr = htonl(INADDR_LOOPBACK);
- isc_sockaddr_fromin(&servers[0], &in, dnsport);
- }
if (have_ipv6) {
memset(&in6, 0, sizeof(in6));
in6.s6_addr[15] = 1;
- isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)],
- &in6, dnsport);
+ isc_sockaddr_fromin6(&servers[0], &in6, dnsport);
+ }
+ if (have_ipv4) {
+ in.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)],
+ &in, dnsport);
}
} else {
ns_total = ns_alloc = lwconf->nsnext;
@@ -1034,7 +1032,7 @@ version(void) {
fputs("nsupdate " VERSION "\n", stderr);
}
-#define PARSE_ARGS_FMT "dDML:y:ghilovk:p:Pr:R::t:Tu:V"
+#define PARSE_ARGS_FMT "46dDML:y:ghilovk:p:Pr:R::t:Tu:V"
static void
pre_parse_args(int argc, char **argv) {
@@ -1042,6 +1040,7 @@ pre_parse_args(int argc, char **argv) {
int ch;
char buf[100];
isc_boolean_t doexit = ISC_FALSE;
+ isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
switch (ch) {
@@ -1053,6 +1052,20 @@ pre_parse_args(int argc, char **argv) {
ISC_MEM_DEBUGRECORD;
break;
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = ISC_TRUE;
+ break;
+
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = ISC_TRUE;
+ break;
+
case '?':
case 'h':
if (isc_commandline_option != '?')
@@ -1060,7 +1073,7 @@ pre_parse_args(int argc, char **argv) {
argv[0], isc_commandline_option);
fprintf(stderr, "usage: nsupdate [-dDi] [-L level] [-l]"
"[-g | -o | -y keyname:secret | -k keyfile] "
- "[-v] [-V] [-P] [-T] [filename]\n");
+ "[-v] [-V] [-P] [-T] [-4 | -6] [filename]\n");
exit(1);
case 'P':
@@ -1110,6 +1123,22 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
debug("parse_args");
while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
switch (ch) {
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv4 networking");
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv6 networking");
+ }
+ break;
case 'd':
debugging = ISC_TRUE;
break;
@@ -3289,6 +3318,16 @@ main(int argc, char **argv) {
isc_app_start();
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ have_ipv4 = ISC_TRUE;
+ }
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ have_ipv6 = ISC_TRUE;
+ }
+ if (!have_ipv4 && !have_ipv6) {
+ fatal("could not find either IPv4 or IPv6");
+ }
+
pre_parse_args(argc, argv);
result = isc_mem_create(0, 0, &gmctx);
diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook
index eaef76c38c..a74d99a0a3 100644
--- a/bin/nsupdate/nsupdate.docbook
+++ b/bin/nsupdate/nsupdate.docbook
@@ -71,6 +71,10 @@
+
+
+
+
filename
@@ -138,6 +142,24 @@
+
+ -4
+
+
+ Use IPv4 only.
+
+
+
+
+
+ -6
+
+
+ Use IPv6 only.
+
+
+
+
-d
diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c
index ad789f68f4..8dfabe075c 100644
--- a/bin/rndc/rndc.c
+++ b/bin/rndc/rndc.c
@@ -92,7 +92,7 @@ static void
usage(int status) {
fprintf(stderr, "\
Usage: %s [-b address] [-c config] [-s server] [-p port]\n\
- [-k key-file ] [-y key] [-r] [-V] command\n\
+ [-k key-file ] [-y key] [-r] [-V] [-4 | -6] command\n\
\n\
command is one of the following:\n\
\n\
@@ -211,6 +211,36 @@ Version: %s\n",
exit(status);
}
+#define CMDLINE_FLAGS "46b:c:hk:Mmp:qrs:Vy:"
+
+static void
+preparse_args(int argc, char **argv) {
+ isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = ISC_TRUE;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = ISC_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ isc_commandline_reset = ISC_TRUE;
+ isc_commandline_index = 1;
+}
+
static void
get_addresses(const char *host, in_port_t port) {
isc_result_t result;
@@ -802,9 +832,22 @@ main(int argc, char **argv) {
isc_commandline_errprint = ISC_FALSE;
- while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:qrs:Vy:"))
- != -1) {
+ preparse_args(argc, argv);
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
+ case '4':
+ if (isc_net_probeipv4() != ISC_R_SUCCESS) {
+ fatal("can't find IPv4 networking");
+ }
+ isc_net_disableipv6();
+ break;
+ case '6':
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ fatal("can't find IPv6 networking");
+ }
+ isc_net_disableipv4();
+ break;
case 'b':
if (inet_pton(AF_INET, isc_commandline_argument,
&in) == 1) {
diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook
index ab29fbe519..7df47db88d 100644
--- a/bin/rndc/rndc.docbook
+++ b/bin/rndc/rndc.docbook
@@ -55,6 +55,10 @@
+
+
+
+
command
@@ -95,6 +99,24 @@
+
+ -4
+
+
+ Use IPv4 only.
+
+
+
+
+
+ -6
+
+
+ Use IPv6 only.
+
+
+
+
-b source-address
diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
index 61f27e9742..707ffe156e 100755
--- a/bin/tests/system/nsupdate/tests.sh
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -90,7 +90,7 @@ pre=`$DIG +short new.other.nil. @10.53.0.1 a -p 5300` || ret=1
ret=0
echo "I:updating zone"
# nsupdate will print a ">" prompt to stdout as it gets each input line.
-$NSUPDATE -l -p 5300 -k ns1/session.key > /dev/null < /dev/null < nsupdate.out 2>&1 << END && ret=1
+$NSUPDATE -4 -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END && ret=1
update add other.nil. 600 in ns ns3.other.nil.
send
END
grep REFUSED nsupdate.out > /dev/null 2>&1 || ret=1
# ...but should work if an A record is inserted first:
-$NSUPDATE -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+$NSUPDATE -4 -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
update add ns4.other.nil 600 in a 10.53.0.1
send
update add other.nil. 600 in ns ns4.other.nil.
@@ -128,7 +128,7 @@ send
END
grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
# ...or if an AAAA record does:
-$NSUPDATE -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+$NSUPDATE -4 -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
update add ns5.other.nil 600 in aaaa 2001:db8::1
send
update add other.nil. 600 in ns ns5.other.nil.
@@ -136,7 +136,7 @@ send
END
grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
# ...or if the NS and A/AAAA are inserted together:
-$NSUPDATE -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+$NSUPDATE -4 -l -p 5300 -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
update add other.nil. 600 in ns ns6.other.nil.
update add ns6.other.nil 600 in a 10.53.0.1
send
@@ -457,7 +457,7 @@ $PERL ../digcomp.pl knowngood.ns1.afterstop dig.out.ns1 || ret=1
ret=0
echo "I:check that 'nsupdate -l' with a missing keyfile reports the missing file"
-$NSUPDATE -l -p 5300 -k ns1/nonexistant.key 2> nsupdate.out < /dev/null
+$NSUPDATE -4 -l -p 5300 -k ns1/nonexistant.key 2> nsupdate.out < /dev/null
grep ns1/nonexistant.key nsupdate.out > /dev/null || ret=1
if test $ret -ne 0
then
@@ -816,6 +816,32 @@ END
grep "couldn't get address for 'unresolvable..': not found" nsupdate.out > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; }
+n=`expr $n + 1`
+ret=0
+echo "I:check nsupdate -4 -6 ($n)"
+$NSUPDATE -4 -6 < nsupdate.out-$n 2>&1 && ret=1
+server 10.53.0.3 5300
+zone delegation.test.
+update del child.delegation.test. 3600 NS foo.example.net.
+update del child.delegation.test. 3600 NS bar.example.net.
+send
+END
+grep "only one of -4 and -6 allowed" nsupdate.out-$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo I:failed; status=1; }
+
+n=`expr $n + 1`
+ret=0
+echo "I:check nsupdate -4 with an IPv6 server address ($n)"
+$NSUPDATE -4 < nsupdate.out-$n 2>&1 && ret=1
+server fd92:7065:b8e:ffff::2 5300
+zone delegation.test.
+update del child.delegation.test. 3600 NS foo.example.net.
+update del child.delegation.test. 3600 NS bar.example.net.
+send
+END
+grep "address family not supported" nsupdate.out-$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo I:failed; status=1; }
+
#
# Add client library tests here
#
diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh
index f1bb1302f3..990ade48d3 100644
--- a/bin/tests/system/rndc/tests.sh
+++ b/bin/tests/system/rndc/tests.sh
@@ -639,5 +639,21 @@ grep "rndc: '' failed: failure" rndc.out.1.test$n > /dev/null
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo "I:check rndc -4 -6 ($n)"
+ret=0
+$RNDCCMD -4 -6 status > rndc.out.1.test$n 2>&1 && ret=1
+grep "only one of -4 and -6 allowed" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:check rndc -4 with an IPv6 server address ($n)"
+ret=0
+$RNDCCMD -4 -s fd92:7065:b8e:ffff::2 status > rndc.out.1.test$n 2>&1 && ret=1
+grep "address family not supported" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:exit status: $status"
[ $status -eq 0 ] || exit 1
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 4871a1b459..3ebdde35e4 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -181,6 +181,13 @@
New Features
+
+
+ nsupdate and rndc now accept
+ command line options -4 and -6
+ which force using only IPv4 or only IPv6, respectively. [RT #45632]
+
+
nsec3hash -r ("rdata order") takes arguments