diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 89cdb15121..1c5a552c48 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,30 +15,15 @@ * SOFTWARE. */ -/* $Id: nsupdate.c,v 1.11 2000/06/29 02:16:44 bwelling Exp $ */ +/* $Id: nsupdate.c,v 1.12 2000/06/30 01:56:14 bwelling Exp $ */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include #include #include +#include #include #include #include @@ -53,6 +38,26 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + #define MXNAME 256 #define MAXCMD 256 #define NAMEBUF 512 @@ -61,67 +66,57 @@ #define MSGTEXT 4069 #define FIND_TIMEOUT 5 -#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC) - #define RESOLV_CONF "/etc/resolv.conf" -extern isc_boolean_t isc_mem_debugging; +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_mutex_t lock; +static isc_condition_t cond; -isc_boolean_t busy= ISC_FALSE, debugging = ISC_FALSE, ddebugging = ISC_FALSE, - have_ipv6 = ISC_FALSE, valid_zonename = ISC_FALSE, - forced_master = ISC_FALSE, is_dst_up = ISC_FALSE; -isc_mutex_t lock; -isc_condition_t cond; +static isc_taskmgr_t *taskmgr = NULL; +static isc_task_t *global_task = NULL; +static isc_mem_t *mctx = NULL; +static dns_dispatchmgr_t *dispatchmgr = NULL; +static dns_requestmgr_t *requestmgr = NULL; +static isc_socketmgr_t *socketmgr = NULL; +static isc_timermgr_t *timermgr = NULL; +static dns_dispatch_t *dispatchv4 = NULL; +static dns_message_t *updatemsg = NULL; +static dns_name_t *zonename = NULL; +static dns_fixedname_t resolvdomain; /* from resolv.conf's domain line */ +static dns_name_t *current_zone; /* Points to one of above, or dns_rootname */ +static dns_name_t *master = NULL; /* Master nameserver, from SOA query */ +static dns_tsigkey_t *key = NULL; +static dns_tsig_keyring_t *keyring = NULL; -isc_taskmgr_t *taskmgr = NULL; -isc_task_t *global_task = NULL; -isc_mem_t *mctx = NULL; -dns_dispatchmgr_t *dispatchmgr = NULL; -dns_requestmgr_t *requestmgr = NULL; -isc_socketmgr_t *socketmgr = NULL; -isc_timermgr_t *timermgr = NULL; -dns_dispatch_t *dispatchv4 = NULL; -dns_message_t *updatemsg = NULL, *findmsg = NULL; -dns_name_t zonename; /* From ZONE command */ -dns_name_t actualzone; /* From SOA query reply */ -dns_name_t resolvdomain; /* From resolv.conf's domain line, if exists */ -dns_name_t *current_zone; /* Points to one of above, or dns_rootname */ -isc_buffer_t resolvbuf; -char resolvstore[MXNAME]; -dns_name_t master; /* Master nameserver, from SOA query */ -dns_tsigkey_t *key = NULL; -dns_tsig_keyring_t *keyring = NULL; +static char nameservername[3][MXNAME]; +static int nameservers; +static int ns_inuse = 0; +static unsigned int ndots = 1; +static char *domain = NULL; +static char *keystr = NULL; +static isc_entropy_t *entp = NULL; -int exitcode = 0; -char server[MXNAME]; -char userzone[MXNAME]; -char nameservername[3][MXNAME]; -int nameservers; -int ns_inuse = 0; -int ndots = 1; -char domain[MXNAME]; -char keynametext[MXNAME]=""; -char keysecret[MXNAME]=""; -dns_name_t keyname; -isc_buffer_t *keynamebuf = NULL; -isc_entropy_t *entp = NULL; +static void sendrequest(int whichns, dns_message_t *msg, + dns_request_t **request); #define STATUS_MORE 0 #define STATUS_SEND 1 #define STATUS_QUIT 2 -#define STATUS_FAIL 3 -#define STATUS_SYNTAX 4 +#define STATUS_SYNTAX 3 -static int -count_dots(char *string) { - char *s; - int i=0; - - s = string; +static unsigned int +count_dots(char *s, isc_boolean_t *last_was_dot) { + int i = 0; + *last_was_dot = ISC_FALSE; while (*s != 0) { - if (*s == '.') + if (*s++ == '.') { i++; - s++; + *last_was_dot = ISC_TRUE; + } else + *last_was_dot = ISC_FALSE; } return (i); } @@ -134,9 +129,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); - if (exitcode == 0) - exitcode = 8; - exit(exitcode); + exit(1); } static void @@ -165,100 +158,94 @@ ddebug(const char *format, ...) { static void check_result(isc_result_t result, const char *msg) { - if (result != ISC_R_SUCCESS) { - exitcode = 1; + if (result != ISC_R_SUCCESS) fatal("%s: %s", msg, isc_result_totext(result)); - } } static void -load_resolv_conf() { +load_resolv_conf(void) { FILE *fp; char rcinput[MXNAME]; char *ptr; ddebug ("load_resolv_conf()"); fp = fopen (RESOLV_CONF, "r"); - if (fp != NULL) { - while (fgets(rcinput, MXNAME, fp) != 0) { - ptr = strtok (rcinput, " \t\r\n"); + if (fp == NULL) + return; + while (fgets(rcinput, MXNAME, fp) != 0) { + ptr = strtok (rcinput, " \t\r\n"); + if (ptr == NULL) + continue; + if (strcasecmp(ptr, "nameserver") == 0) { + ddebug ("Got a nameserver line"); + ptr = strtok (NULL, " \t\r\n"); if (ptr != NULL) { - if (strcasecmp(ptr, "nameserver") == 0) { - ddebug ("Got a nameserver line"); - ptr = strtok (NULL, " \t\r\n"); - if (ptr != NULL) { - if (nameservers < 3) { - strncpy(nameservername - [nameservers], - ptr,MXNAME); - nameservers++; - } - } - } else if (strcasecmp(ptr, "options") == 0) { - ptr = strtok(NULL, " \t\r\n"); - if (ptr != NULL) { - if (strncasecmp(ptr, "ndots:", - 6) == 0) { - ndots = atoi(&ptr[6]); - ddebug ("ndots is " - "%d.", - ndots); - } - } - /* XXXMWS Searchlist not supported! */ - } else if ((strcasecmp(ptr, "domain") == 0) && - (domain[0] == 0 )){ - while ((ptr = strtok(NULL, " \t\r\n")) - != NULL) { - strncpy(domain, ptr, MXNAME); - } - } - + if (nameservers >= 3) + continue; + strncpy(nameservername[nameservers], + ptr, MXNAME); + nameservers++; } + } else if (strcasecmp(ptr, "options") == 0) { + char *endp; + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + continue; + if (strncasecmp(ptr, "ndots:", 6) == 0) { + ndots = strtol(&ptr[6], &endp, 10); + if (*endp != 0) + fatal("ndots is not numeric\n"); + ddebug ("ndots is %d.", ndots); + } + /* XXXMWS Searchlist not supported! */ + } else if (strcasecmp(ptr, "domain") == 0 && domain == NULL) { + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + continue; + domain = isc_mem_strdup(mctx, ptr); + if (domain == NULL) + fatal("out of memory"); } - fclose (fp); } + fclose (fp); } static void -reset_system() { +reset_system(void) { isc_result_t result; ddebug ("reset_system()"); /* If the update message is still around, destroy it */ if (updatemsg != NULL) - dns_message_destroy(&updatemsg); - if (findmsg != NULL) - dns_message_destroy(&findmsg); - result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, - &updatemsg); - check_result (result, "dns_message_create"); + dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); + else { + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, + &updatemsg); + check_result (result, "dns_message_create"); + } updatemsg->opcode = dns_opcode_update; - valid_zonename = ISC_FALSE; - if (VALID_NAME(&zonename)) - dns_name_free(&zonename, mctx); - if (VALID_NAME(&actualzone)) - dns_name_free(&actualzone, mctx); - if (VALID_NAME(&master)) - dns_name_free(&master, mctx); - if (domain[0] != 0) - current_zone = &resolvdomain; + if (zonename != NULL) { + dns_name_free(zonename, mctx); + isc_mem_put(mctx, zonename, sizeof(dns_name_t)); + zonename = NULL; + } + if (master != NULL) { + dns_name_free(master, mctx); + isc_mem_put(mctx, master, sizeof(dns_name_t)); + master = NULL; + } + if (domain != NULL) + current_zone = dns_fixedname_name(&resolvdomain); else current_zone = dns_rootname; } static void -setup_system(){ +setup_system(void) { isc_result_t result; isc_sockaddr_t bind_any; isc_buffer_t buf; - int secretsize; - unsigned char *secretstore; - isc_buffer_t secretsrc; - isc_buffer_t secretbuf; - isc_lex_t *lex = NULL; - isc_stdtime_t now; ddebug("setup_system()"); @@ -266,13 +253,11 @@ 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); - isc_mem_debugging = ISC_FALSE; - - load_resolv_conf(); - result = isc_app_start(); check_result(result, "isc_app_start"); @@ -287,6 +272,8 @@ setup_system(){ result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); + load_resolv_conf(); + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); check_result(result, "dns_dispatchmgr_create"); @@ -324,384 +311,156 @@ setup_system(){ dispatchv4, NULL, &requestmgr); check_result(result, "dns_requestmgr_create"); - if (domain[0] != 0) { - dns_name_init(&resolvdomain, NULL); - isc_buffer_init(&resolvbuf, resolvstore, NAMEBUF); - dns_name_setbuffer(&resolvdomain, &resolvbuf); + if (domain != NULL) { + dns_fixedname_init(&resolvdomain); isc_buffer_init(&buf, domain, strlen(domain)); isc_buffer_add(&buf, strlen(domain)); - result = dns_name_fromtext(&resolvdomain, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(dns_fixedname_name(&resolvdomain), + &buf, dns_rootname, ISC_FALSE, NULL); check_result(result, "dns_name_fromtext"); - current_zone = &resolvdomain; + current_zone = dns_fixedname_name(&resolvdomain); } - else { + else current_zone = dns_rootname; - } - if (keysecret[0] != 0) { + if (keystr != NULL) { + dns_fixedname_t fkeyname; + dns_name_t *keyname; + isc_buffer_t keynamesrc; + char *secretstr; + unsigned char *secret; + int secretlen; + isc_buffer_t secretsrc, secretbuf; + isc_lex_t *lex = NULL; + char *s; + debug("Creating key..."); + + s = strchr(keystr, ':'); + if (s == NULL || s == keystr || *s++ == 0) + fatal("key option must specify keyname:secret\n"); + secretstr = s + 1; + result = dns_tsigkeyring_create(mctx, &keyring); check_result(result, "dns_tsigkeyringcreate"); - result = isc_buffer_allocate(mctx, &keynamebuf, MXNAME); - check_result(result, "isc_buffer_allocate"); - dns_name_init(&keyname, NULL); - check_result(result, "dns_name_init"); - isc_buffer_putstr(keynamebuf, keynametext); - secretsize = strlen(keysecret) * 3 / 4; - secretstore = isc_mem_get(mctx, secretsize); - ENSURE (secretstore != NULL); - isc_buffer_init(&secretsrc, keysecret, strlen(keysecret)); - isc_buffer_add(&secretsrc, strlen(keysecret)); - isc_buffer_init(&secretbuf, secretstore, secretsize); - result = isc_lex_create(mctx, strlen(keysecret), &lex); + + dns_fixedname_init(&fkeyname); + keyname = dns_fixedname_name(&fkeyname); + + isc_buffer_init(&keynamesrc, keystr, s - keystr); + + debug("namefromtext"); + result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, + ISC_FALSE, NULL); + check_result(result, "dns_name_fromtext"); + + secretlen = strlen(secretstr) * 3 / 4; + secret = isc_mem_allocate(mctx, secretlen); + 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); if (result != ISC_R_SUCCESS) { - printf (";; Couldn't create key %s: %s\n", - keynametext, isc_result_totext(result)); + printf (";; Couldn't create key from %s: %s\n", + keystr, isc_result_totext(result)); isc_lex_close(lex); isc_lex_destroy(&lex); goto SYSSETUP_FAIL; } - secretsize = isc_buffer_usedlength(&secretbuf); + secretlen = isc_buffer_usedlength(&secretbuf); debug("close"); isc_lex_close(lex); isc_lex_destroy(&lex); - isc_stdtime_get(&now); - debug("namefromtext"); - result = dns_name_fromtext(&keyname, keynamebuf, - dns_rootname, ISC_FALSE, - keynamebuf); - if (result != ISC_R_SUCCESS) { - printf (";; Couldn't create key %s: %s\n", - keynametext, dns_result_totext(result)); - goto SYSSETUP_FAIL; - } - debug("tsigkey"); - result = dns_tsigkey_create(&keyname, dns_tsig_hmacmd5_name, - secretstore, secretsize, - ISC_TRUE, NULL, now, now, mctx, + debug("keycreate"); + result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name, + secret, secretlen, + ISC_TRUE, NULL, 0, 0, mctx, keyring, &key); if (result != ISC_R_SUCCESS) { - printf (";; Couldn't create key %s: %s\n", - keynametext, dns_result_totext(result)); + printf (";; Couldn't create key from %s: %s\n", + keystr, dns_result_totext(result)); } - isc_mem_put(mctx, secretstore, secretsize); - dns_name_invalidate(&keyname); - isc_buffer_free(&keynamebuf); + isc_mem_free(mctx, secret); return; SYSSETUP_FAIL: - isc_mem_put(mctx, secretstore, secretsize); - dns_name_invalidate(&keyname); - isc_buffer_free(&keynamebuf); + isc_mem_free(mctx, secret); dns_tsigkeyring_destroy(&keyring); } } -static void -set_key(char *key) { - char *nameptr; - char *secptr; - - debug("set_key"); - nameptr = strtok(key, ": \t\r\n"); - if (nameptr == NULL) { - fputs ("Need a key entry\n", stderr); - return; - } - secptr = strtok(NULL, " \t\r\n"); - if (secptr == NULL) { - fputs ("Need a key entry\n", stderr); - return; - } - strncpy (keynametext, nameptr, MXNAME); - strncpy (keysecret, secptr, MXNAME); -} - static void parse_args(int argc, char **argv) { - int rc; - char **rv; + int ch; debug("parse_args"); - rc = argc; - rv = argv; - for (rc--, rv++; rc > 0; rc--, rv++) { - if (strcasecmp(rv[0], "-d") == 0) + while ((ch = isc_commandline_parse(argc, argv, "dDMy:vk:")) != -1) { + switch (ch) { + case 'd': + debugging = ISC_TRUE; + break; + case 'D': /* was -dd */ debugging = ISC_TRUE; - else if (strcasecmp(rv[0], "-dd") == 0) { ddebugging = ISC_TRUE; - debug ("Just turned on debugging"); - } else if (strcasecmp(rv[0], "-dm") == 0) { + break; + case 'M': /* was -dm */ + debugging = ISC_TRUE; ddebugging = ISC_TRUE; isc_mem_debugging = ISC_TRUE; - } else if (strncasecmp(rv[0],"-y", 2) == 0) { - debug ("In -y test"); - if (rv[0][2] != 0) - set_key(&rv[0][2]); - else { - rc--; - rv++; - if (rc == 0) { - fputs ("Need a key entry\n", stderr); - return; - } - set_key(rv[0]); - } - } else if (strcasecmp(rv[0], "-v") == 0) - fputs ("Virtual Circuit mode not currently " - "implemented.\n", stderr); - else if (strcasecmp(rv[0], "-k") == 0) - fputs ("TSIG not currently implemented.", - stderr); + break; + case 'y': + keystr = isc_commandline_argument; + break; + case 'v': + fprintf(stderr, "Virtual Circuit mode not " + "currently implemented.\n"); + break; + case 'k': + fprintf(stderr, "TSIG not currently implemented."); + break; + default: + fprintf(stderr, "%s: invalid argument -%c\n", + argv[0], ch); + exit(1); + } } } -static void -check_and_add_zone(dns_name_t *namein) { - - ddebug ("check_and_add_zone()"); - - if (valid_zonename) - return; - dns_name_init(&zonename, NULL); - dns_name_dup(namein, mctx, &zonename); - current_zone = &zonename; - valid_zonename = ISC_TRUE; -} - static isc_uint16_t -make_rrset_prereq(dns_rdataclass_t rdclass) { - isc_result_t result; - char *nameptr, *typeptr; - dns_name_t *name = NULL; - isc_buffer_t *buf = NULL; - isc_buffer_t source; - isc_textregion_t typeregion; - dns_rdataset_t *rdataset = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdatatype_t rdatatype; - dns_rdata_t *rdata = NULL; - dns_name_t *rn = current_zone; - - ddebug ("make_rrset_prereq()"); - nameptr = strtok(NULL, " \t\r\n"); - if (nameptr == NULL) { - puts ("failed to read owner name"); - return STATUS_SYNTAX; - } - - typeptr = strtok(NULL, " \t\r\n"); - if (typeptr == NULL) { - puts ("failed to read owner type"); - return STATUS_SYNTAX; - } - - result = dns_message_gettempname(updatemsg, &name); - check_result(result, "dns_message_gettempname"); - result = isc_buffer_allocate(mctx, &buf, NAMEBUF); - check_result(result, "isc_buffer_allocate"); - dns_name_init(name, NULL); - dns_name_setbuffer(name, buf); - dns_message_takebuffer(updatemsg, &buf); - isc_buffer_init(&source, nameptr, strlen(nameptr)); - isc_buffer_add(&source, strlen(nameptr)); - if (count_dots(nameptr) > ndots) - rn = dns_rootname; - result = dns_name_fromtext(name, &source, rn, - ISC_FALSE, NULL); - check_result(result, "dns_name_fromtext"); - - check_and_add_zone(name); - - typeregion.base = typeptr; - typeregion.length = strlen(typeptr); - result = dns_rdatatype_fromtext(&rdatatype, &typeregion); - check_result (result, "dns_rdatatype_fromtext"); - - result = dns_message_gettemprdatalist(updatemsg, &rdatalist); - check_result(result, "dns_message_gettemprdatalist"); - result = dns_message_gettemprdataset(updatemsg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdatalist_init(rdatalist); - rdatalist->type = rdatatype; - rdatalist->rdclass = rdclass; - rdatalist->covers = 0; - rdatalist->ttl = 0; - result = dns_message_gettemprdata(updatemsg, &rdata); - check_result(result, "dns_message_gettemprdata"); - rdata->data = NULL; - rdata->length = 0; - rdata->rdclass = rdclass; - rdata->type = rdatatype; - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - dns_rdataset_init(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); - return STATUS_MORE; -} - - -static isc_uint16_t -make_domain_prereq(dns_rdataclass_t rdclass) { +make_prereq(isc_boolean_t ispositive, isc_boolean_t isrrset) { isc_result_t result; char *ptr; dns_name_t *name = NULL; - isc_buffer_t *buf = NULL; - isc_buffer_t source; - dns_rdataset_t *rdataset = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdata_t *rdata = NULL; - dns_name_t *rn = current_zone; - - ddebug ("make_domain_prereq()"); - ptr = strtok(NULL, " \t\r\n"); - if (ptr == NULL) { - puts ("failed to read owner name"); - return STATUS_SYNTAX; - } - - result = dns_message_gettempname(updatemsg, &name); - check_result(result, "dns_message_gettempname"); - result = isc_buffer_allocate(mctx, &buf, NAMEBUF); - check_result(result, "isc_buffer_allocate"); - dns_name_init(name, NULL); - dns_name_setbuffer(name, buf); - dns_message_takebuffer(updatemsg, &buf); - isc_buffer_init(&source, ptr, strlen(ptr)); - isc_buffer_add(&source, strlen(ptr)); - if (count_dots(ptr) > ndots) - rn = dns_rootname; - result = dns_name_fromtext(name, &source, rn, - ISC_FALSE, NULL); - check_result(result, "dns_name_fromtext"); - - check_and_add_zone(name); - - result = dns_message_gettemprdatalist(updatemsg, &rdatalist); - check_result(result, "dns_message_gettemprdatalist"); - result = dns_message_gettemprdataset(updatemsg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdatalist_init(rdatalist); - rdatalist->type = dns_rdatatype_any; - rdatalist->rdclass = rdclass; - rdatalist->covers = 0; - rdatalist->ttl = 0; - result = dns_message_gettemprdata(updatemsg, &rdata); - check_result(result, "dns_message_gettemprdata"); - rdata->data = NULL; - rdata->length = 0; - rdata->rdclass = rdclass; - rdata->type = dns_rdatatype_any; - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - dns_rdataset_init(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); - return STATUS_MORE; -} - -static isc_uint16_t -evaluate_prereq() { - char *ptr; - - ddebug ("evaluate_prereq()"); - ptr = strtok(NULL, " \t\r\n"); - if (ptr == NULL) { - puts ("failed to read operation code"); - return STATUS_SYNTAX; - } - if (strcasecmp(ptr,"nxdomain") == 0) - return(make_domain_prereq(dns_rdataclass_none)); - if (strcasecmp(ptr,"yxdomain") == 0) - return(make_domain_prereq(dns_rdataclass_any)); - if (strcasecmp(ptr,"nxrrset") == 0) - return(make_rrset_prereq(dns_rdataclass_none)); - if (strcasecmp(ptr,"yxrrset") == 0) - return(make_rrset_prereq(dns_rdataclass_any)); - printf ("incorrect operation code: %s\n",ptr); - return(STATUS_SYNTAX); -} - -static isc_uint16_t -evaluate_server() { - char *ptr; - - ddebug ("evaluate_server()"); - ptr = strtok(NULL, " \t\r\n"); - if (ptr == NULL) { - puts ("failed to read server name"); - return STATUS_SYNTAX; - } - strncpy(server, ptr, MXNAME); - return STATUS_MORE; -} - -static isc_uint16_t -evaluate_zone() { - char *ptr; - dns_name_t name; - isc_buffer_t source, *buf = NULL; - isc_result_t result; - - ddebug ("evaluate_zone()"); - ptr = strtok(NULL, " \t\r\n"); - if (ptr == NULL) { - puts ("failed to read zone name"); - return STATUS_SYNTAX; - } - strncpy(userzone, ptr, MXNAME); - - result = isc_buffer_allocate(mctx, &buf, NAMEBUF); - check_result(result, "isc_buffer_allocate"); - dns_name_init(&name, NULL); - dns_name_setbuffer(&name, buf); - isc_buffer_init(&source, ptr, strlen(ptr)); - isc_buffer_add(&source, strlen(ptr)); - result = dns_name_fromtext(&name, &source, dns_rootname, - ISC_FALSE, NULL); - check_result(result, "dns_name_fromtext"); - - check_and_add_zone(&name); - - isc_buffer_free(&buf); - - return STATUS_MORE; -} - -static isc_uint16_t -update_add() { - isc_result_t result; - isc_lex_t *lex = NULL; - isc_buffer_t *buf = NULL; isc_buffer_t *namebuf = NULL; isc_buffer_t source; - dns_name_t *name = NULL; - isc_uint16_t ttl; - char *ptr, *type, *data; - dns_rdatatype_t rdatatype; - dns_rdatacallbacks_t callbacks; - dns_rdata_t *rdata = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdataset_t *rdataset = NULL; isc_textregion_t region; + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; dns_name_t *rn = current_zone; + unsigned int dots; + isc_boolean_t last; - ddebug ("update_add()"); + ddebug ("make_prereq()"); + + /* + * Read the owner name + */ ptr = strtok(NULL, " \t\r\n"); if (ptr == NULL) { - puts ("failed to read owner name"); - return STATUS_SYNTAX; + puts("failed to read owner name"); + return (STATUS_SYNTAX); } result = dns_message_gettempname(updatemsg, &name); @@ -713,42 +472,289 @@ update_add() { dns_message_takebuffer(updatemsg, &namebuf); isc_buffer_init(&source, ptr, strlen(ptr)); isc_buffer_add(&source, strlen(ptr)); - if (count_dots(ptr) > ndots) + dots = count_dots(ptr, &last); + if (dots > ndots || last) + rn = dns_rootname; + result = dns_name_fromtext(name, &source, rn, + ISC_FALSE, NULL); + check_result(result, "dns_name_fromtext"); + + /* + * If this is an rrset prereq, read the class or type. + */ + if (isrrset) { + char *ptr; + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + puts("failed to read class or type"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } + region.base = ptr; + region.length = strlen(ptr); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + puts("failed to read type"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } + region.base = ptr; + region.length = strlen(ptr); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + check_result(result, "dns_rdatatype_fromtext"); + } else { + rdataclass = dns_rdataclass_in; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + check_result(result, "dns_rdatatype_fromtext"); + } + } else + rdatatype = dns_rdatatype_any; + + + result = dns_message_gettemprdatalist(updatemsg, &rdatalist); + check_result(result, "dns_message_gettemprdatalist"); + result = dns_message_gettemprdataset(updatemsg, &rdataset); + check_result(result, "dns_message_gettemprdataset"); + dns_rdatalist_init(rdatalist); + rdatalist->type = rdatatype; + if (ispositive) + rdatalist->rdclass = dns_rdataclass_any; + else + rdatalist->rdclass = dns_rdataclass_none; + rdatalist->covers = 0; + rdatalist->ttl = 0; + result = dns_message_gettemprdata(updatemsg, &rdata); + check_result(result, "dns_message_gettemprdata"); + rdata->data = NULL; + rdata->length = 0; + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatatype; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdataset_init(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); + return (STATUS_MORE); +} + +static isc_uint16_t +evaluate_prereq(void) { + char *ptr; + isc_boolean_t ispositive, isrrset; + + ddebug ("evaluate_prereq()"); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + puts ("failed to read operation code"); + return (STATUS_SYNTAX); + } + if (strcasecmp(ptr, "nxdomain") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_FALSE; + } else if (strcasecmp(ptr, "yxdomain") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_FALSE; + } else if (strcasecmp(ptr, "nxrrset") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_TRUE; + } else if (strcasecmp(ptr, "yxrrset") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_TRUE; + } else { + printf("incorrect operation code: %s\n", ptr); + return (STATUS_SYNTAX); + } + return (make_prereq(ispositive, isrrset)); +} + +static isc_uint16_t +evaluate_server(void) { + printf("The server statement is not currently implemented.\n"); + return (STATUS_MORE); +} + +static isc_uint16_t +evaluate_zone(void) { + printf("The zone statement is not currently implemented.\n"); + return (STATUS_MORE); +#if 0 + char *ptr; + dns_name_t *name; + isc_buffer_t src; + isc_result_t result; + dns_fixedname_t fname; + + ddebug ("evaluate_zone()"); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + printf("failed to read zone name"); + return (STATUS_SYNTAX); + } else if (zonename != NULL) + dns_name_free(zonename, mctx); + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + + isc_buffer_init(&src, ptr, strlen(ptr)); + isc_buffer_add(&src, strlen(ptr)); + + result = dns_name_fromtext(name, &src, dns_rootname, ISC_FALSE, NULL); + check_result(result, "dns_name_fromtext"); + + if (zonename == NULL) { + zonename = isc_mem_get(mctx, sizeof(dns_name_t)); + if (zonename == NULL) + fatal("out of memory"); + } + dns_name_init(zonename, NULL); + dns_name_dup(name, mctx, zonename); + current_zone = zonename; + + return (STATUS_MORE); +#endif +} + +static isc_uint16_t +update_addordelete(isc_boolean_t isdelete) { + isc_result_t result; + isc_lex_t *lex = NULL; + isc_buffer_t *buf = NULL; + isc_buffer_t *namebuf = NULL; + isc_buffer_t source; + dns_name_t *name = NULL; + isc_uint16_t ttl; + char *ptr, *data; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdatacallbacks_t callbacks; + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t *rdataset = NULL; + isc_textregion_t region; + dns_name_t *rn = current_zone; + char *endp; + unsigned int dots; + isc_boolean_t last; + + ddebug ("update_addordelete()"); + + /* + * Read the owner name + */ + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + puts ("failed to read owner name"); + return (STATUS_SYNTAX); + } + + result = dns_message_gettempname(updatemsg, &name); + check_result(result, "dns_message_gettempname"); + result = isc_buffer_allocate(mctx, &namebuf, NAMEBUF); + check_result(result, "isc_buffer_allocate"); + dns_name_init(name, NULL); + dns_name_setbuffer(name, namebuf); + dns_message_takebuffer(updatemsg, &namebuf); + isc_buffer_init(&source, ptr, strlen(ptr)); + isc_buffer_add(&source, strlen(ptr)); + dots = count_dots(ptr, &last); + if (dots > ndots || last) rn = dns_rootname; result = dns_name_fromtext(name, &source, rn, ISC_FALSE, NULL); check_result(result, "dns_name_fromtext"); - check_and_add_zone(name); + result = dns_message_gettemprdata(updatemsg, &rdata); + check_result(result, "dns_message_gettemprdata"); + rdata->rdclass = 0; + rdata->type = 0; + rdata->data = NULL; + rdata->length = 0; + + /* + * If this is an add, read the TTL and verify that it's numeric. + */ + if (!isdelete) { + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + puts ("failed to read owner ttl"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } + ttl = strtol(ptr, &endp, 0); + if (*endp != 0) { + printf("ttl '%s' is not numeric\n", ptr); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } + } else + ttl = 0; + + /* + * Read the class or type. + */ ptr = strtok(NULL, " \t\r\n"); if (ptr == NULL) { - puts ("failed to read owner ttl"); - dns_message_puttempname(updatemsg, &name); - return STATUS_SYNTAX; + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + goto doneparsing; + } else { + puts ("failed to read class or type"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } } - ttl = atoi(ptr); - - type = strtok(NULL, " \t\r\n"); - if (type == NULL) { - puts ("failed to read owner type"); - dns_message_puttempname(updatemsg, &name); - return STATUS_SYNTAX; + region.base = ptr; + region.length = strlen(ptr); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + goto doneparsing; + } else { + puts ("failed to read type"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } + } + region.base = ptr; + region.length = strlen(ptr); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + check_result(result, "dns_rdatatype_fromtext"); + } else { + rdataclass = dns_rdataclass_in; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + check_result(result, "dns_rdatatype_fromtext"); } data = strtok(NULL, " \t\r\n"); if (data == NULL) { - puts ("failed to read owner data"); - dns_message_puttempname(updatemsg, &name); - return STATUS_SYNTAX; + if (isdelete) { + rdataclass = dns_rdataclass_any; + goto doneparsing; + } else { + puts ("failed to read owner data"); + dns_message_puttempname(updatemsg, &name); + return (STATUS_SYNTAX); + } } result = isc_lex_create(mctx, NAMEHINT, &lex); check_result(result, "isc_lex_create"); - region.base = type; - region.length = strlen(type); - result = dns_rdatatype_fromtext(&rdatatype, ®ion); - check_result(result, "dns_rdatatype_fromtext"); isc_buffer_invalidate(&source); isc_buffer_init(&source, data, strlen(data)); @@ -758,16 +764,18 @@ update_add() { result = isc_buffer_allocate(mctx, &buf, MXNAME); check_result(result, "isc_buffer_allocate"); - result = dns_message_gettemprdata(updatemsg, &rdata); - check_result(result, "dns_message_gettemprdata"); dns_rdatacallbacks_init_stdio(&callbacks); - result = dns_rdata_fromtext(rdata, dns_rdataclass_in, rdatatype, + result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex, current_zone, ISC_FALSE, buf, &callbacks); + dns_message_takebuffer(updatemsg, &buf); check_result(result, "dns_rdata_fromtext"); isc_lex_destroy(&lex); - check_and_add_zone(name); + if (isdelete) + rdataclass = dns_rdataclass_none; + + doneparsing: result = dns_message_gettemprdatalist(updatemsg, &rdatalist); check_result(result, "dns_message_gettemprdatalist"); @@ -775,7 +783,7 @@ update_add() { check_result(result, "dns_message_gettemprdataset"); dns_rdatalist_init(rdatalist); rdatalist->type = rdatatype; - rdatalist->rdclass = dns_rdataclass_in; + rdatalist->rdclass = rdataclass; rdatalist->covers = rdatatype; rdatalist->ttl = ttl; ISC_LIST_INIT(rdatalist->rdata); @@ -785,151 +793,33 @@ update_add() { ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); - dns_message_takebuffer(updatemsg, &buf); - return STATUS_MORE; + return (STATUS_MORE); } -/* XXXMWS add and delete share so much code, they should be collapsed. */ static isc_uint16_t -update_delete() { - isc_result_t result; - isc_lex_t *lex = NULL; - isc_buffer_t *namebuf = NULL; - isc_buffer_t *buf = NULL; - isc_buffer_t source; - dns_name_t *name = NULL; - char *ptr, *typeptr, *dataptr = NULL; - dns_rdatatype_t rdatatype; - dns_rdatacallbacks_t callbacks; - dns_rdata_t *rdata = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdataset_t *rdataset = NULL; - isc_textregion_t typeregion; - dns_name_t *rn = current_zone; - - ddebug ("update_delete()"); - ptr = strtok(NULL, " \t\r\n"); - if (ptr == NULL) { - puts ("failed to read owner name"); - return STATUS_SYNTAX; - } - - result = dns_message_gettempname(updatemsg, &name); - check_result(result, "dns_message_gettempname"); - result = isc_buffer_allocate(mctx, &namebuf, NAMEBUF); - check_result(result, "isc_buffer_allocate"); - dns_name_init(name, NULL); - dns_name_setbuffer(name, namebuf); - dns_message_takebuffer(updatemsg, &namebuf); - isc_buffer_init(&source, ptr, strlen(ptr)); - isc_buffer_add(&source, strlen(ptr)); - if (count_dots(ptr) > ndots) - rn = dns_rootname; - result = dns_name_fromtext(name, &source, rn, - ISC_FALSE, NULL); - check_result(result, "dns_name_fromtext"); - - check_and_add_zone(name); - - typeptr = strtok(NULL, " \t\r\n"); - if (typeptr != NULL) { - dataptr = strtok(NULL, " \t\r\n"); - } - - if (typeptr != NULL) { - typeregion.base = typeptr; - typeregion.length = strlen(typeptr); - result = dns_rdatatype_fromtext(&rdatatype, &typeregion); - check_result(result, "dns_rdatatype_fromtext"); - isc_buffer_invalidate(&source); - } - else { - rdatatype = dns_rdatatype_any; - } - - if (dataptr != NULL) { - result = isc_lex_create(mctx, NAMEHINT, &lex); - check_result(result, "isc_lex_create"); - - isc_buffer_init(&source, dataptr, strlen(dataptr)); - isc_buffer_add(&source, strlen(dataptr)); - 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"); - result = dns_message_gettemprdata(updatemsg, &rdata); - check_result(result, "dns_message_gettemprdata"); - dns_rdatacallbacks_init_stdio(&callbacks); - result = dns_rdata_fromtext(rdata, dns_rdataclass_in, - rdatatype, lex, current_zone, - ISC_FALSE, buf, &callbacks); - check_result(result, "dns_rdata_fromtext"); - isc_lex_destroy(&lex); - - result = dns_message_gettemprdatalist(updatemsg, &rdatalist); - check_result(result, "dns_message_gettemprdatalist"); - result = dns_message_gettemprdataset(updatemsg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdatalist_init(rdatalist); - rdatalist->type = rdatatype; - rdatalist->rdclass = dns_rdataclass_none; - rdatalist->covers = 0; - rdatalist->ttl = 0; - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - dns_rdataset_init(rdataset); - dns_rdatalist_tordataset(rdatalist, rdataset); - isc_buffer_free(&buf); - } - else { - result = dns_message_gettemprdatalist(updatemsg, &rdatalist); - check_result(result, "dns_message_gettemprdatalist"); - result = dns_message_gettemprdataset(updatemsg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdatalist_init(rdatalist); - rdatalist->type = rdatatype; - rdatalist->rdclass = dns_rdataclass_any; - rdatalist->covers = 0; - rdatalist->ttl = 0; - result = dns_message_gettemprdata(updatemsg, &rdata); - check_result(result, "dns_message_gettemprdata"); - rdata->data = NULL; - rdata->length = 0; - rdata->rdclass = dns_rdataclass_any; - rdata->type = rdatatype; - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - dns_rdataset_init(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_UPDATE); - return STATUS_MORE; -} - - -static isc_uint16_t -evaluate_update() { +evaluate_update(void) { char *ptr; + isc_boolean_t isdelete; ddebug ("evaluate_update()"); ptr = strtok(NULL, " \t\r\n"); if (ptr == NULL) { puts ("failed to read operation code"); - return STATUS_SYNTAX; + return (STATUS_SYNTAX); } - if (strcasecmp(ptr,"delete") == 0) - return(update_delete()); - if (strcasecmp(ptr,"add") == 0) - return(update_add()); - printf ("incorrect operation code: %s\n",ptr); - return(STATUS_SYNTAX); + if (strcasecmp(ptr, "delete") == 0) + isdelete = ISC_TRUE; + else if (strcasecmp(ptr, "add") == 0) + isdelete = ISC_FALSE; + else { + printf ("incorrect operation code: %s\n",ptr); + return (STATUS_SYNTAX); + } + return (update_addordelete(isdelete)); } static void -show_message() { +show_message(void) { isc_result_t result; char store[MSGTEXT]; isc_buffer_t buf; @@ -937,15 +827,18 @@ show_message() { ddebug ("show_message()"); isc_buffer_init(&buf, store, MSGTEXT); result = dns_message_totext(updatemsg, 0, &buf); - check_result(result, "dns_message_totext"); - printf ("Outgoing update query:\n%.*s", - (int)isc_buffer_usedlength(&buf), - (char*)isc_buffer_base(&buf)); + if (result != ISC_R_SUCCESS) { + printf("Failed to concert message to text format.\n"); + return; + } + printf("Outgoing update query:\n%.*s", + (int)isc_buffer_usedlength(&buf), + (char*)isc_buffer_base(&buf)); } static isc_uint16_t -get_next_command() { +get_next_command(void) { char cmdline[MAXCMD]; char *ptr; @@ -972,14 +865,14 @@ get_next_command() { return(STATUS_SEND); if (strcasecmp(ptr,"show") == 0) { show_message(); - return(STATUS_MORE); + return (STATUS_MORE); } - printf ("incorrect section name: %s\n",ptr); - return(STATUS_SYNTAX); + printf ("incorrect section name: %s\n", ptr); + return (STATUS_SYNTAX); } static isc_boolean_t -user_interaction() { +user_interaction(void) { isc_uint16_t result = STATUS_MORE; ddebug ("user_interaction()"); @@ -987,10 +880,8 @@ user_interaction() { result = get_next_command(); } if (result == STATUS_SEND) - return ISC_TRUE; - if (result == STATUS_FAIL) - exitcode = 1; - return ISC_FALSE; + return (ISC_TRUE); + return (ISC_FALSE); } @@ -1031,8 +922,8 @@ update_completed(isc_task_t *task, isc_event_t *event) { REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); reqev = (dns_requestevent_t *)event; if (reqev->result != ISC_R_SUCCESS) { - printf ("; Communication with server failed: %d-%s\n", - reqev->result, isc_result_totext(reqev->result)); + printf ("; Communication with server failed: %s\n", + isc_result_totext(reqev->result)); goto done; } @@ -1052,14 +943,14 @@ update_completed(isc_task_t *task, isc_event_t *event) { done: dns_request_destroy(&reqev->request); isc_event_free(&event); - isc_mutex_lock(&lock); + LOCK(&lock); busy = ISC_FALSE; - isc_condition_signal(&cond); - isc_mutex_unlock(&lock); + SIGNAL(&cond); + UNLOCK(&lock); } static void -send_update() { +send_update(void) { isc_result_t result; isc_sockaddr_t sockaddr; dns_request_t *request = NULL; @@ -1072,8 +963,10 @@ send_update() { result = dns_message_gettempname(updatemsg, &name); check_result(result, "dns_message_gettempname"); + if (zonename == NULL) + fatal("don't have a valid zone yet."); dns_name_init(name, NULL); - dns_name_clone(&actualzone, name); + dns_name_clone(zonename, name); result = dns_message_gettemprdataset(updatemsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); dns_rdataset_makequestion(rdataset, dns_rdataclass_in, @@ -1083,7 +976,7 @@ send_update() { dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); isc_buffer_init(&buf, servername, MXNAME); - result = dns_name_totext(&master, ISC_TRUE, &buf); + result = dns_name_totext(master, ISC_TRUE, &buf); check_result(result, "dns_name_totext"); servername[isc_buffer_usedlength(&buf)] = 0; @@ -1099,50 +992,52 @@ send_update() { static void find_completed(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = NULL; - isc_sockaddr_t sockaddr; dns_request_t *request = NULL; - isc_result_t result; + isc_result_t result, eresult; dns_message_t *rcvmsg = NULL; + dns_message_t *soaquery = NULL; dns_section_t section; dns_name_t *name = NULL; - dns_rdataset_t *rdataset = NULL; + dns_rdataset_t *soaset = NULL; dns_rdata_soa_t soa; - dns_rdata_t rdata; - isc_buffer_t buf; - char bufstore[MSGTEXT]; + dns_rdata_t soarr; + int pass = 0; UNUSED(task); ddebug ("find_completed()"); REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); reqev = (dns_requestevent_t *)event; - if (reqev->result != ISC_R_SUCCESS) { - printf ("; Communication with %s failed: %d-%s\n", - nameservername[ns_inuse], reqev->result, - isc_result_totext(reqev->result)); + request = reqev->request; + eresult = reqev->result; + soaquery = reqev->ev_arg; + + isc_event_free(&event); + reqev = NULL; + + if (eresult != ISC_R_SUCCESS) { + printf ("; Communication with %s failed: %s\n", + nameservername[ns_inuse], isc_result_totext(eresult)); ns_inuse++; - if (ns_inuse >= nameservers) { + if (ns_inuse >= nameservers) fatal ("Couldn't talk to any default nameserver."); - } - get_address(nameservername[ns_inuse], 53, &sockaddr); - ddebug("Destroying %lx[%lx]", &reqev->request, - reqev->request); - dns_request_destroy(&reqev->request); - isc_event_free(&event); - result = dns_request_create(requestmgr, findmsg, &sockaddr, - 0, NULL, - FIND_TIMEOUT, global_task, - find_completed, NULL, &request); - check_result(result, "dns_result_create"); + ddebug("Destroying request [%lx]", request); + dns_request_destroy(&request); + sendrequest(ns_inuse, soaquery, &request); return; } + dns_message_destroy(&soaquery); + ddebug ("About to create rcvmsg"); 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(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); check_result(result, "dns_message_totext"); @@ -1151,111 +1046,141 @@ find_completed(isc_task_t *task, isc_event_t *event) { (char*)isc_buffer_base(&buf)); } - /* XXXMWS Really shouldn't use firstname here */ - section = DNS_SECTION_ANSWER; + if (rcvmsg->rcode != dns_rcode_noerror && + rcvmsg->rcode != dns_rcode_nxdomain) + fatal("response to SOA query was unsuccessful"); + + lookforsoa: + if (pass == 0) + section = DNS_SECTION_ANSWER; + else if (pass == 1) + section = DNS_SECTION_AUTHORITY; + else + fatal("response to SOA query didn't contain an SOA"); + + result = dns_message_firstname(rcvmsg, section); if (result != ISC_R_SUCCESS) { - section = DNS_SECTION_AUTHORITY; - result = dns_message_firstname(rcvmsg, section); - check_result(result, "dns_message_firstname"); + pass++; + goto lookforsoa; + } + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rcvmsg, section, &name); + soaset = NULL; + result = dns_message_findtype(name, dns_rdatatype_soa, 0, + &soaset); + if (result == ISC_R_SUCCESS) + break; + result = dns_message_nextname(rcvmsg, section); } - dns_message_currentname(rcvmsg, section, &name); - dns_name_init(&actualzone, NULL); - result = dns_name_dup(name, mctx, &actualzone); - /* Name is just a reference, so this is safe. */ - name = NULL; + if (soaset == NULL) { + pass++; + goto lookforsoa; + } if (debugging) { - isc_buffer_clear(&buf); - result = dns_name_totext(&actualzone, ISC_FALSE, &buf); - check_result(result, "dns_name_totext"); - printf ("Found zone name: %.*s\n", - (int)isc_buffer_usedlength(&buf), - (char*)isc_buffer_base(&buf)); + char namestr[1025]; + dns_name_format(name, namestr, sizeof(namestr)); + printf ("Found zone name: %s\n", namestr); } - ddebug("Finding name"); - result = dns_message_findname(rcvmsg, section, &actualzone, - dns_rdatatype_soa, 0, - &name, &rdataset); - check_result(result, "Couldn't find SOA in reply"); - - result = dns_rdataset_first(rdataset); + result = dns_rdataset_first(soaset); check_result(result, "dns_rdataset_first"); - dns_rdataset_current(rdataset, &rdata); - ddebug("tostruct"); - result = dns_rdata_tostruct(&rdata, &soa, mctx); + + dns_rdata_init(&soarr); + dns_rdataset_current(soaset, &soarr); + result = dns_rdata_tostruct(&soarr, &soa, NULL); check_result(result, "dns_rdata_tostruct"); - dns_name_init(&master, NULL); + ddebug("Duping master"); - result = dns_name_dup(&soa.origin, mctx, &master); + INSIST(master == NULL); + master = isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(master, NULL); + result = dns_name_dup(&soa.origin, mctx, master); check_result(result, "dns_name_dup"); - if (debugging) { - isc_buffer_clear(&buf); - result = dns_name_totext(&master, ISC_FALSE, &buf); - check_result(result, "dns_name_totext"); - printf ("The master is: %.*s\n", - (int)isc_buffer_usedlength(&buf), - (char*)isc_buffer_base(&buf)); - } + ddebug("Duping zonename"); + INSIST(zonename == NULL); + zonename = isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(zonename, NULL); + result = dns_name_dup(name, mctx, zonename); + check_result(result, "dns_name_dup"); dns_rdata_freestruct(&soa); + + if (debugging) { + char namestr[1025]; + dns_name_format(master, namestr, sizeof(namestr)); + printf ("The master is: %s\n", namestr); + } + dns_message_destroy(&rcvmsg); - dns_request_destroy(&reqev->request); - isc_event_free(&event); + dns_request_destroy(&request); ddebug ("Out of find_completed"); send_update(); } static void -start_update() { +sendrequest(int whichns, dns_message_t *msg, dns_request_t **request) { + isc_sockaddr_t sockaddr; + isc_result_t result; + + get_address(nameservername[whichns], 53, &sockaddr); + result = dns_request_create(requestmgr, msg, &sockaddr, + 0, NULL, FIND_TIMEOUT, global_task, + find_completed, msg, request); + check_result(result, "dns_request_create"); +} + +static void +start_update(void) { isc_result_t result; dns_rdataset_t *rdataset = NULL; dns_name_t *name = NULL; - isc_sockaddr_t sockaddr; dns_request_t *request = NULL; + dns_message_t *soaquery = NULL; + dns_name_t *firstname; ddebug ("start_update()"); result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, - &findmsg); + &soaquery); check_result(result, "dns_message_create"); - findmsg->flags |= DNS_MESSAGEFLAG_RD; + soaquery->flags |= DNS_MESSAGEFLAG_RD; - result = dns_message_gettempname(findmsg, &name); + result = dns_message_gettempname(soaquery, &name); check_result(result, "dns_message_gettempname"); - result = dns_message_gettemprdataset(findmsg, &rdataset); + result = dns_message_gettemprdataset(soaquery, &rdataset); check_result(result, "dns_message_gettemprdataset"); dns_rdataset_makequestion(rdataset, dns_rdataclass_in, dns_rdatatype_soa); - dns_name_init(name, NULL); - if (!valid_zonename) { - fatal ("don't have a valid zone yet."); + result = dns_message_firstname(updatemsg, DNS_SECTION_UPDATE); + if (result != ISC_R_SUCCESS) { + busy = ISC_FALSE; + return; } - dns_name_clone(&zonename, name); + firstname = NULL; + dns_message_currentname(updatemsg, DNS_SECTION_UPDATE, &firstname); + dns_name_init(name, NULL); + dns_name_clone(firstname, name); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); - dns_message_addname(findmsg, name, DNS_SECTION_QUESTION); + dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); ns_inuse = 0; - get_address(nameservername[0], 53, &sockaddr); - result = dns_request_create(requestmgr, findmsg, &sockaddr, - 0, NULL, - FIND_TIMEOUT, global_task, - find_completed, NULL, &request); - check_result(result, "dns_request_create"); + sendrequest(ns_inuse, soaquery, &request); } static void -free_lists() { - ddebug ("free_lists()"); +cleanup(void) { + ddebug ("cleanup()"); if (key != NULL) { ddebug("Freeing key"); @@ -1263,10 +1188,6 @@ free_lists() { dns_tsigkey_detach(&key); } - if (keynamebuf != NULL) { - ddebug("Freeing keynamebuf"); - isc_buffer_free(&keynamebuf); - } if (keyring != NULL) { debug ("Freeing keyring %lx", keyring); dns_tsigkeyring_destroy(&keyring); @@ -1274,18 +1195,21 @@ free_lists() { if (updatemsg != NULL) dns_message_destroy(&updatemsg); - if (findmsg != NULL) - dns_message_destroy(&findmsg); - if (VALID_NAME(&actualzone)) { - ddebug("Freeing actualzone"); - dns_name_free(&actualzone, mctx); + if (zonename != NULL) { + dns_name_free(zonename, mctx); + isc_mem_put(mctx, zonename, sizeof(dns_name_t)); + zonename = NULL; } - if (VALID_NAME(&zonename)) { - ddebug("Freeing zonename"); - dns_name_free(&zonename, mctx); + if (master != NULL) { + dns_name_free(master, mctx); + isc_mem_put(mctx, master, sizeof(dns_name_t)); + master = NULL; + } + if (domain != NULL) { + isc_mem_free(mctx, domain); + domain = NULL; } - if (is_dst_up) { debug ("Destroy DST lib"); dst_lib_destroy(); @@ -1322,14 +1246,11 @@ free_lists() { if (isc_mem_debugging) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); - - exit(0); } int main(int argc, char **argv) { isc_result_t result; - parse_args(argc, argv); @@ -1338,8 +1259,7 @@ main(int argc, char **argv) { check_result(result, "isc_mutex_init"); result = isc_condition_init(&cond); check_result(result, "isc_condition_init"); - result = isc_mutex_trylock(&lock); - check_result(result, "isc_mutex_trylock"); + LOCK(&lock); while (ISC_TRUE) { reset_system(); @@ -1347,17 +1267,15 @@ main(int argc, char **argv) { break; busy = ISC_TRUE; start_update(); - while (busy) { - result = isc_condition_wait(&cond, &lock); - check_result(result, "isc_condition_wait"); - } + while (busy) + WAIT(&cond, &lock); } puts (""); ddebug ("Fell through app_run"); isc_mutex_destroy(&lock); isc_condition_destroy(&cond); - free_lists(0); + cleanup(); return (0); }