]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] Add -4/-6 command line options to nsupdate and rndc
authorMichał Kępień <michal@isc.org>
Wed, 16 Aug 2017 14:01:39 +0000 (16:01 +0200)
committerMichał Kępień <michal@isc.org>
Tue, 29 Aug 2017 08:21:54 +0000 (10:21 +0200)
4691. [func] Add -4/-6 command line options to nsupdate and rndc.
[RT #45632]

CHANGES
bin/nsupdate/nsupdate.c
bin/nsupdate/nsupdate.docbook
bin/rndc/rndc.c
bin/rndc/rndc.docbook
bin/tests/system/nsupdate/tests.sh
bin/tests/system/rndc/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index a45d476b4691212683842c108d1d159374d94d20..ff1982dc76f5800ede0e8c37b185afb6bcfa7917 100644 (file)
--- 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]
 
index 70d7a55277dd527829dfdd1e6b55825fda2659c5..06e536622bafcb6bdb01898932fa0985d73ca2e8 100644 (file)
@@ -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);
index eaef76c38cfe9ad2ceb5de69e659d7136222719d..a74d99a0a315a2397a0289d8cc25b8415fdda4cc 100644 (file)
       <arg choice="opt" rep="norepeat"><option>-T</option></arg>
       <arg choice="opt" rep="norepeat"><option>-P</option></arg>
       <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+      <group choice="opt" rep="norepeat">
+       <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+       <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+      </group>
       <arg choice="opt" rep="norepeat">filename</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
 
     <variablelist>
+      <varlistentry>
+       <term>-4</term>
+       <listitem>
+         <para>
+           Use IPv4 only.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-6</term>
+       <listitem>
+         <para>
+           Use IPv6 only.
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term>-d</term>
        <listitem>
index ad789f68f45e7301fd65601ea7a44339c410ef0c..8dfabe075ccff5f9bb68c81d8fa11ca8caff1d7c 100644 (file)
@@ -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) {
index ab29fbe519dda20a25abffeaf7838b070c94006a..7df47db88d6e4fef12b41ac05aebe5936c68389b 100644 (file)
       <arg choice="opt" rep="norepeat"><option>-r</option></arg>
       <arg choice="opt" rep="norepeat"><option>-V</option></arg>
       <arg choice="opt" rep="norepeat"><option>-y <replaceable class="parameter">key_id</replaceable></option></arg>
+      <group choice="opt" rep="norepeat">
+       <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+       <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+      </group>
       <arg choice="req" rep="norepeat">command</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
 
     <variablelist>
+      <varlistentry>
+       <term>-4</term>
+       <listitem>
+         <para>
+           Use IPv4 only.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-6</term>
+       <listitem>
+         <para>
+           Use IPv6 only.
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term>-b <replaceable class="parameter">source-address</replaceable></term>
        <listitem>
index 61f27e9742d0318c6d7a08f09a4cb581bdabd58a..707ffe156ebe3519a74f1ef7c0f7e8b4001724ca 100755 (executable)
@@ -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 <<END || ret=1
+$NSUPDATE -4 -l -p 5300 -k ns1/session.key > /dev/null <<END || ret=1
 zone other.nil.
 update add new.other.nil. 600 IN A 10.10.10.1
 send
@@ -114,13 +114,13 @@ $PERL ../digcomp.pl knowngood.ns1.after dig.out.ns1 || ret=1
 ret=0
 echo "I:testing zone consistency checks"
 # inserting an NS record without a corresponding A or AAAA record should fail
-$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 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 <<END > 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 <<END > 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
 #
index f1bb1302f38f4025d2e64bd6df0e0d4b6bba81d1..990ade48d3e2fa5e107ddda9783eb0e42dd2f59d 100644 (file)
@@ -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
index 4871a1b4598bc5c58687b5a03750df6f1dbd60c2..3ebdde35e4d351dcdffe7b0427e716b684d274fc 100644 (file)
 
   <section xml:id="relnotes_features"><info><title>New Features</title></info>
     <itemizedlist>
+      <listitem>
+       <para>
+         <command>nsupdate</command> and <command>rndc</command> now accept
+         command line options <command>-4</command> and <command>-6</command>
+         which force using only IPv4 or only IPv6, respectively. [RT #45632]
+       </para>
+      </listitem>
       <listitem>
        <para>
          <command>nsec3hash -r</command> ("rdata order") takes arguments