pullup: nsupdate mega-pullup patch from Mike

This commit is contained in:
Andreas Gustafsson 2000-10-20 18:32:20 +00:00
parent 2f67fb6fc5
commit ad42b21192

View 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);
}