]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
pullup: nsupdate mega-pullup patch from Mike
authorAndreas Gustafsson <source@isc.org>
Fri, 20 Oct 2000 18:32:20 +0000 (18:32 +0000)
committerAndreas Gustafsson <source@isc.org>
Fri, 20 Oct 2000 18:32:20 +0000 (18:32 +0000)
bin/nsupdate/nsupdate.c

index e546bda03499d0f84a5784bd2dde21c36b198e4f..e3026ab389588ad6e966c99dd421aa4c4fbb3fdd 100644 (file)
@@ -1,21 +1,21 @@
 /*
  * Copyright (C) 2000  Internet Software Consortium.
- * 
+ *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM 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.
  */
 
-/* $Id: nsupdate.c,v 1.8.2.12 2000/10/19 17:13:22 gson Exp $ */
+/* $Id: nsupdate.c,v 1.8.2.13 2000/10/20 18:32:20 gson Exp $ */
 
 #include <config.h>
 
@@ -33,12 +33,11 @@ extern int h_errno;
 #include <isc/app.h>
 #include <isc/base64.h>
 #include <isc/buffer.h>
-#include <isc/condition.h>
 #include <isc/commandline.h>
 #include <isc/entropy.h>
+#include <isc/event.h>
 #include <isc/lex.h>
 #include <isc/mem.h>
-#include <isc/mutex.h>
 #include <isc/region.h>
 #include <isc/sockaddr.h>
 #include <isc/socket.h>
@@ -51,6 +50,7 @@ extern int h_errno;
 #include <dns/callbacks.h>
 #include <dns/dispatch.h>
 #include <dns/events.h>
+#include <dns/fixedname.h>
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/rdata.h>
@@ -68,29 +68,29 @@ extern int h_errno;
 #include <lwres/lwres.h>
 #include <lwres/net.h>
 
-#define MXNAME 256
-#define MAXPNAME 1025
-#define MAXCMD 1024
+#define MAXCMD (4 * 1024)
+#define INITDATA (32 * 1024)
+#define MAXDATA (64 * 1024)
 #define NAMEBUF 512
 #define WORDLEN 512
-#define PACKETSIZE 2048
-#define MSGTEXT 4096
+#define PACKETSIZE ((64 * 1024) - 1)
+#define INITTEXT (2 * 1024)
+#define MAXTEXT (128 * 1024)
 #define FIND_TIMEOUT 5
 #define TTL_MAX 2147483647     /* Maximum signed 32 bit integer. */
 
 #define DNSDEFAULTPORT 53
+#define MAXNAME 1024
 
 #define RESOLV_CONF "/etc/resolv.conf"
 
-static isc_boolean_t busy = ISC_FALSE;
 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
 static isc_boolean_t have_ipv6 = ISC_FALSE;
 static isc_boolean_t is_dst_up = ISC_FALSE;
 static isc_boolean_t usevc = ISC_FALSE;
-static isc_mutex_t lock;
-static isc_condition_t cond;
 static isc_taskmgr_t *taskmgr = NULL;
 static isc_task_t *global_task = NULL;
+static isc_event_t *global_event = NULL;
 static isc_mem_t *mctx = NULL;
 static dns_dispatchmgr_t *dispatchmgr = NULL;
 static dns_requestmgr_t *requestmgr = NULL;
@@ -104,7 +104,6 @@ static dns_name_t *origin; /* Points to one of above, or dns_rootname */
 static dns_fixedname_t fuserzone;
 static dns_name_t *userzone = NULL;
 static dns_tsigkey_t *key = NULL;
-static dns_tsig_keyring_t *keyring = NULL;
 static lwres_context_t *lwctx = NULL;
 static lwres_conf_t *lwconf;
 static isc_sockaddr_t *servers;
@@ -132,7 +131,7 @@ static void
 fatal(const char *format, ...) {
        va_list args;
 
-       va_start(args, format); 
+       va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
        fprintf(stderr, "\n");
@@ -144,7 +143,7 @@ debug(const char *format, ...) {
        va_list args;
 
        if (debugging) {
-               va_start(args, format); 
+               va_start(args, format);
                vfprintf(stderr, format, args);
                va_end(args);
                fprintf(stderr, "\n");
@@ -156,7 +155,7 @@ ddebug(const char *format, ...) {
        va_list args;
 
        if (ddebugging) {
-               va_start(args, format); 
+               va_start(args, format);
                vfprintf(stderr, format, args);
                va_end(args);
                fprintf(stderr, "\n");
@@ -252,17 +251,12 @@ setup_key(void) {
        dns_fixedname_t fkeyname;
        dns_name_t *keyname;
 
-       result = dns_tsigkeyring_create(mctx, &keyring);
-       check_result(result, "dns_tsigkeyringcreate");
-
        dns_fixedname_init(&fkeyname);
        keyname = dns_fixedname_name(&fkeyname);
 
        if (keystr != NULL) {
                isc_buffer_t keynamesrc;
                char *secretstr;
-               isc_buffer_t secretsrc;
-               isc_lex_t *lex = NULL;
                char *s;
 
                debug("Creating key...");
@@ -285,27 +279,16 @@ setup_key(void) {
                if (secret == NULL)
                        fatal("out of memory");
 
-               isc_buffer_init(&secretsrc, secretstr, strlen(secretstr));
-               isc_buffer_add(&secretsrc, strlen(secretstr));
-
                isc_buffer_init(&secretbuf, secret, secretlen);
-
-               result = isc_lex_create(mctx, strlen(secretstr), &lex);
-               check_result(result, "isc_lex_create");
-               result = isc_lex_openbuffer(lex, &secretsrc);
-               check_result(result, "isc_lex_openbuffer");
-               result = isc_base64_tobuffer(lex, &secretbuf, -1);
+               result = isc_base64_decodestring(mctx, secretstr, &secretbuf);
                if (result != ISC_R_SUCCESS) {
                        fprintf(stderr, "Couldn't create key from %s: %s\n",
                                keystr, isc_result_totext(result));
-                       isc_lex_close(lex);
-                       isc_lex_destroy(&lex);
                        goto failure;
                }
+
                secretlen = isc_buffer_usedlength(&secretbuf);
                debug("close");
-               isc_lex_close(lex);
-               isc_lex_destroy(&lex);
        } else {
                dst_key_t *dstkey = NULL;
 
@@ -333,11 +316,11 @@ setup_key(void) {
                dst_key_free(&dstkey);
                                    
        }
-               
+
        debug("keycreate");
        result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name,
                                    secret, secretlen, ISC_TRUE, NULL, 0, 0,
-                                   mctx, keyring, &key);
+                                   mctx, NULL, &key);
        if (result != ISC_R_SUCCESS) {
                char *str;
                if (keystr != NULL)
@@ -354,7 +337,6 @@ setup_key(void) {
 
        if (secret != NULL)
                isc_mem_free(mctx, secret);
-       dns_tsigkeyring_destroy(&keyring);
 }
 
 static void
@@ -368,15 +350,6 @@ setup_system(void) {
 
        ddebug("setup_system()");
 
-       /*
-        * Warning: This is not particularly good randomness.  We'll
-        * just use random() now for getting id values, but doing so
-        * does NOT insure that id's can't be guessed.
-        *
-        * XXX Shouldn't random() be called somewhere if this is here?
-        */
-       srandom(getpid() + (int)&setup_system);
-
        dns_result_register();
 
        result = isc_net_probeipv4();
@@ -545,7 +518,7 @@ parse_args(int argc, char **argv) {
                case 'M': /* was -dm */
                        debugging = ISC_TRUE;
                        ddebugging = ISC_TRUE;
-                       isc_mem_debugging = ISC_TRUE;
+                       isc_mem_debugging = 1;
                        break;
                case 'y':
                        keystr = isc_commandline_argument;
@@ -621,31 +594,42 @@ parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
        dns_rdatacallbacks_t callbacks;
        isc_result_t result;
        dns_name_t *rn;
+       int bufsz = INITDATA;
 
        while (*cmdline != 0 && isspace((unsigned char)*cmdline))
                cmdline++;
 
        if (*cmdline != 0) {
-               result = isc_lex_create(mctx, WORDLEN, &lex);
-               check_result(result, "isc_lex_create"); 
-
-               isc_buffer_init(&source, cmdline, strlen(cmdline));
-               isc_buffer_add(&source, strlen(cmdline));
-               result = isc_lex_openbuffer(lex, &source);
-               check_result(result, "isc_lex_openbuffer");
-
-               result = isc_buffer_allocate(mctx, &buf, MXNAME);
-               check_result(result, "isc_buffer_allocate");
-               dns_rdatacallbacks_init_stdio(&callbacks);
+               dns_rdatacallbacks_init(&callbacks);
                if (userzone != NULL)
                        rn = userzone;
                else
                        rn = origin;
-               result = dns_rdata_fromtext(*rdatap, rdataclass, rdatatype,
-                                           lex, rn, ISC_FALSE, buf,
-                                           &callbacks);
+               do {
+                       result = isc_lex_create(mctx, strlen(cmdline), &lex);
+                       check_result(result, "isc_lex_create");
+                       isc_buffer_init(&source, cmdline, strlen(cmdline));
+                       isc_buffer_add(&source, strlen(cmdline));
+                       result = isc_lex_openbuffer(lex, &source);
+                       check_result(result, "isc_lex_openbuffer");
+                       if (buf != NULL)
+                               isc_buffer_free(&buf);
+                       if (bufsz > MAXDATA) {
+                               fprintf(stderr, "couldn't allocate enough "
+                                       "space for the rdata\n");
+                               exit(1);
+                       }
+                       result = isc_buffer_allocate(mctx, &buf, bufsz);
+                       check_result(result, "isc_buffer_allocate");
+                       result = dns_rdata_fromtext(*rdatap, rdataclass,
+                                                   rdatatype,
+                                                   lex, rn, ISC_FALSE, buf,
+                                                   &callbacks);
+                       bufsz *= 2;
+                       isc_lex_destroy(&lex);
+               } while (result == ISC_R_NOSPACE);
+               check_result(result, "dns_rdata_fromtext");
                dns_message_takebuffer(msg, &buf);
-               isc_lex_destroy(&lex);
                if (result != ISC_R_SUCCESS)
                        return (STATUS_MORE);
        }
@@ -743,7 +727,7 @@ make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
        ISC_LIST_INIT(rdatalist->rdata);
        ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
        dns_rdataset_init(rdataset);
-       dns_rdatalist_tordataset(rdatalist, rdataset);          
+       dns_rdatalist_tordataset(rdatalist, rdataset);
        ISC_LIST_INIT(name->list);
        ISC_LIST_APPEND(name->list, rdataset, link);
        dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
@@ -1014,23 +998,37 @@ evaluate_update(char *cmdline) {
 }
 
 static void
-show_message(void) {
+show_message(dns_message_t *msg) {
        isc_result_t result;
-       char store[MSGTEXT];
-       isc_buffer_t buf;
+       isc_buffer_t *buf = NULL;
+       int bufsz;
 
        ddebug("show_message()");
-       isc_buffer_init(&buf, store, MSGTEXT);
-       result = dns_message_totext(updatemsg, 0, &buf);
+       bufsz = INITTEXT;
+       do { 
+               if (bufsz > MAXTEXT) {
+                       fprintf(stderr, "couldn't allocate large enough "
+                               "buffer to display message\n");
+                       exit(1);
+               }
+               if (buf != NULL)
+                       isc_buffer_free(&buf);
+               result = isc_buffer_allocate(mctx, &buf, bufsz);
+               check_result(result, "isc_buffer_allocate");
+               result = dns_message_totext(msg, 0, buf);
+               bufsz *= 2;
+       } while (result == ISC_R_NOSPACE);
        if (result != ISC_R_SUCCESS) {
-               fprintf(stderr, "Failed to concert message to text format.\n");
+               fprintf(stderr, "Failed to convert message to text format.\n");
+               isc_buffer_free(&buf);
                return;
        }
        printf("Outgoing update query:\n%.*s",
-              (int)isc_buffer_usedlength(&buf),
-              (char*)isc_buffer_base(&buf));
+              (int)isc_buffer_usedlength(buf),
+              (char*)isc_buffer_base(buf));
+       isc_buffer_free(&buf);
 }
-       
+
 
 static isc_uint16_t
 get_next_command(void) {
@@ -1040,8 +1038,9 @@ get_next_command(void) {
 
        ddebug("get_next_command()");
        fprintf(stdout, "> ");
-       fgets (cmdlinebuf, MAXCMD, stdin);
-       cmdline = cmdlinebuf;
+       cmdline = fgets(cmdlinebuf, MAXCMD, stdin);
+       if (cmdline == NULL)
+               return (STATUS_QUIT);
        word = nsu_strsep(&cmdline, " \t\r\n");
 
        if (feof(stdin))
@@ -1061,7 +1060,7 @@ get_next_command(void) {
        if (strcasecmp(word, "send") == 0)
                return (STATUS_SEND);
        if (strcasecmp(word, "show") == 0) {
-               show_message();
+               show_message(updatemsg);
                return (STATUS_MORE);
        }
        fprintf(stderr, "incorrect section name: %s\n", word);
@@ -1082,23 +1081,17 @@ user_interaction(void) {
 }
 
 static void
-done_update(isc_boolean_t acquirelock) {
-       if (acquirelock)
-               LOCK(&lock);
-       busy = ISC_FALSE;
-       SIGNAL(&cond);
-       if (acquirelock)
-               UNLOCK(&lock);
+done_update(void) {
+       isc_event_t *event = global_event;
+       isc_task_send(global_task, &event);
 }
 
 static void
 update_completed(isc_task_t *task, isc_event_t *event) {
        dns_requestevent_t *reqev = NULL;
        isc_result_t result;
-       isc_buffer_t buf;
        dns_message_t *rcvmsg = NULL;
-       char bufstore[MSGTEXT];
-       
+
        UNUSED(task);
 
        ddebug("updated_completed()");
@@ -1112,21 +1105,38 @@ update_completed(isc_task_t *task, isc_event_t *event) {
 
        result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
        check_result(result, "dns_message_create");
-       result = dns_request_getresponse(reqev->request, rcvmsg, ISC_TRUE);
+       result = dns_request_getresponse(reqev->request, rcvmsg,
+                                        ISC_TRUE);
        check_result(result, "dns_request_getresponse");
        if (debugging) {
-               isc_buffer_init(&buf, bufstore, MSGTEXT);
-               result = dns_message_totext(rcvmsg, 0, &buf);
+               isc_buffer_t *buf = NULL;
+               int bufsz;
+
+               bufsz = INITTEXT;
+               do { 
+                       if (bufsz > MAXTEXT) {
+                               fprintf (stderr, "couldn't allocate large "
+                                        "enough buffer to display message\n");
+                               exit(1);
+                       }
+                       if (buf != NULL)
+                               isc_buffer_free(&buf);
+                       result = isc_buffer_allocate(mctx, &buf, bufsz);
+                       check_result(result, "isc_buffer_allocate");
+                       result = dns_message_totext(rcvmsg, 0, buf);
+                       bufsz *= 2;
+               } while (result == ISC_R_NOSPACE);
                check_result(result, "dns_message_totext");
                fprintf(stderr, "\nReply from update query:\n%.*s\n",
-                       (int)isc_buffer_usedlength(&buf),
-                       (char*)isc_buffer_base(&buf));
+                       (int)isc_buffer_usedlength(buf),
+                       (char*)isc_buffer_base(buf));
+               isc_buffer_free(&buf);
        }
        dns_message_destroy(&rcvmsg);
  done:
        dns_request_destroy(&reqev->request);
        isc_event_free(&event);
-       done_update(ISC_TRUE);
+       done_update();
 }
 
 static void
@@ -1195,7 +1205,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
 
        if (eresult != ISC_R_SUCCESS) {
                char addrbuf[ISC_SOCKADDR_FORMATSIZE];
-       
+
                isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
                fprintf(stderr, "; Communication with %s failed: %s\n",
                       addrbuf, isc_result_totext(eresult));
@@ -1216,19 +1226,31 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
        ddebug("About to create rcvmsg");
        result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
        check_result(result, "dns_message_create");
-       result = dns_request_getresponse(request, rcvmsg, ISC_TRUE);
+       result = dns_request_getresponse(request, rcvmsg,
+                                        ISC_TRUE);
        check_result(result, "dns_request_getresponse");
        section = DNS_SECTION_ANSWER;
        if (debugging) {
-               isc_buffer_t buf;
-               char bufstore[MSGTEXT];
-
-               isc_buffer_init(&buf, bufstore, MSGTEXT);
-               result = dns_message_totext(rcvmsg, 0, &buf);
+               isc_buffer_t *buf = NULL;
+               int bufsz;
+               bufsz = INITTEXT;
+               do {
+                       if (buf != NULL)
+                               isc_buffer_free(&buf);
+                       if (bufsz > MAXTEXT) {
+                               fprintf(stderr, "couldn't allocate enough "
+                                        "space for debugging message\n");
+                               exit(1);
+                       }
+                       result = isc_buffer_allocate(mctx, &buf, bufsz);
+                       check_result(result, "isc_buffer_allocate");
+                       result = dns_message_totext(rcvmsg, 0, buf);
+               } while (result == ISC_R_NOSPACE);
                check_result(result, "dns_message_totext");
                fprintf(stderr, "Reply from SOA query:\n%.*s\n",
-                       (int)isc_buffer_usedlength(&buf),
-                       (char*)isc_buffer_base(&buf));
+                       (int)isc_buffer_usedlength(buf),
+                       (char*)isc_buffer_base(buf));
+               isc_buffer_free(&buf);
        }
 
        if (rcvmsg->rcode != dns_rcode_noerror &&
@@ -1266,7 +1288,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
        }
 
        if (debugging) {
-               char namestr[MAXPNAME];
+               char namestr[MAXNAME];
                dns_name_format(name, namestr, sizeof(namestr));
                fprintf(stderr, "Found zone name: %s\n", namestr);
        }
@@ -1288,7 +1310,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
                zonename = name;
 
        if (debugging) {
-               char namestr[MAXPNAME];
+               char namestr[MAXNAME];
                dns_name_format(&master, namestr, sizeof(namestr));
                fprintf(stderr, "The master is: %s\n", namestr);
        }
@@ -1296,7 +1318,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
        if (userserver != NULL)
                serveraddr = userserver;
        else {
-               char serverstr[MXNAME];
+               char serverstr[MAXNAME+1];
                isc_buffer_t buf;
 
                isc_buffer_init(&buf, serverstr, sizeof(serverstr));
@@ -1351,7 +1373,7 @@ start_update(void) {
 
        result = dns_message_firstname(updatemsg, DNS_SECTION_UPDATE);
        if (result != ISC_R_SUCCESS) {
-               done_update(ISC_FALSE);
+               done_update();
                return;
        }
 
@@ -1396,15 +1418,9 @@ cleanup(void) {
 
        if (key != NULL) {
                debug("Freeing key");
-               dns_tsigkey_setdeleted(key);
                dns_tsigkey_detach(&key);
        }
 
-       if (keyring != NULL) {
-               debug("Freeing keyring %lx", keyring);
-               dns_tsigkeyring_destroy(&keyring);
-       }
-
        if (updatemsg != NULL)
                dns_message_destroy(&updatemsg);
 
@@ -1423,7 +1439,7 @@ cleanup(void) {
        lwres_context_destroy(&lwctx);
 
        isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
-               
+
        ddebug("Shutting down request manager");
        dns_requestmgr_shutdown(requestmgr);
        dns_requestmgr_detach(&requestmgr);
@@ -1439,6 +1455,10 @@ cleanup(void) {
        ddebug("Ending task");
        isc_task_detach(&global_task);
 
+       ddebug("Destroying event task");
+       if (global_event != NULL)
+               isc_event_free(&global_event);
+
        ddebug("Shutting down task manager");
        isc_taskmgr_destroy(&taskmgr);
 
@@ -1454,33 +1474,44 @@ cleanup(void) {
        isc_mem_destroy(&mctx);
 }
 
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+       isc_boolean_t more;
+
+       UNUSED(task);
+
+       if (global_event == NULL)
+               global_event = event;
+
+       reset_system();
+       more = user_interaction();
+       if (!more) {
+               isc_app_shutdown();
+               return;
+       }
+       start_update();
+       return;
+}
+
 int
 main(int argc, char **argv) {
         isc_result_t result;
 
+       isc_app_start();
+
         parse_args(argc, argv);
 
         setup_system();
-        result = isc_mutex_init(&lock);
-        check_result(result, "isc_mutex_init");
-        result = isc_condition_init(&cond);
-        check_result(result, "isc_condition_init");
-       LOCK(&lock);
-
-        while (ISC_TRUE) {
-               reset_system();
-                if (!user_interaction())
-                       break;
-               busy = ISC_TRUE;
-               start_update();
-               while (busy)
-                       WAIT(&cond, &lock);
-        }
+
+       result = isc_app_onrun(mctx, global_task, getinput, NULL);
+       check_result(result, "isc_app_onrun");
+
+       (void)isc_app_run();
 
         fprintf(stdout, "\n");
-        isc_mutex_destroy(&lock);
-        isc_condition_destroy(&cond);
         cleanup();
 
+       isc_app_finish();
+
         return (0);
 }