mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-24 23:57:30 -04:00
Add ixfr support to dig, as:
dig domain.nil. ixfr=12345 where 12345 is version you are ixrf'ing against (testing still in progress of this option)
This commit is contained in:
parent
ac37a32d23
commit
d12ed0876f
5 changed files with 246 additions and 49 deletions
|
|
@ -939,6 +939,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
|
|||
lookup->trace_root = trace;
|
||||
lookup->ns_search_only = ns_search_only;
|
||||
lookup->doing_xfr = ISC_FALSE;
|
||||
lookup->ixfr_serial = 0;
|
||||
lookup->defname = ISC_FALSE;
|
||||
lookup->identify = identify;
|
||||
lookup->recurse = recurse;
|
||||
|
|
@ -964,14 +965,20 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
|
|||
} else {
|
||||
if (have_host) {
|
||||
ENSURE(lookup != NULL);
|
||||
if (istype(rv[0])) {
|
||||
if (strncmp(rv[0],"ixfr=",5) == 0) {
|
||||
strcpy(lookup->rttext, "ixfr");
|
||||
lookup->ixfr_serial =
|
||||
atoi(&rv[0][5]);
|
||||
continue;
|
||||
}
|
||||
if (istype(rv[0])) {
|
||||
strncpy(lookup->rttext, rv[0], MXRD);
|
||||
continue;
|
||||
} else if (isclass(rv[0])) {
|
||||
strncpy(lookup->rctext, rv[0],
|
||||
MXRD);
|
||||
continue;
|
||||
}
|
||||
} else if (isclass(rv[0])) {
|
||||
strncpy(lookup->rctext, rv[0],
|
||||
MXRD);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
lookup = isc_mem_allocate(mctx,
|
||||
sizeof(struct dig_lookup));
|
||||
|
|
@ -991,6 +998,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
|
|||
lookup->origin = NULL;
|
||||
lookup->use_my_server_list = ISC_FALSE;
|
||||
lookup->doing_xfr = ISC_FALSE;
|
||||
lookup->ixfr_serial = 0;
|
||||
lookup->defname = ISC_FALSE;
|
||||
lookup->trace = ISC_TF(trace || ns_search_only);
|
||||
lookup->trace_root = trace;
|
||||
|
|
@ -1064,6 +1072,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
|
|||
lookup->origin = NULL;
|
||||
lookup->use_my_server_list = ISC_FALSE;
|
||||
lookup->doing_xfr = ISC_FALSE;
|
||||
lookup->ixfr_serial = 0;
|
||||
lookup->defname = ISC_FALSE;
|
||||
lookup->trace = ISC_TF(trace || ns_search_only);
|
||||
lookup->trace_root = trace;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ extern int h_errno;
|
|||
#include <dns/rdatatype.h>
|
||||
#include <dns/rdatalist.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
|
||||
#include <dig/dig.h>
|
||||
|
||||
|
|
@ -260,6 +261,7 @@ dig_lookup_t
|
|||
looknew->timer = NULL;
|
||||
looknew->xfr_q = NULL;
|
||||
looknew->doing_xfr = lookold->doing_xfr;
|
||||
looknew->ixfr_serial = lookold->ixfr_serial;
|
||||
looknew->defname = lookold->defname;
|
||||
looknew->trace = lookold->trace;
|
||||
looknew->trace_root = lookold->trace_root;
|
||||
|
|
@ -739,6 +741,67 @@ next_origin(dns_message_t *msg, dig_query_t *query) {
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
insert_soa(dig_lookup_t *lookup) {
|
||||
isc_result_t result;
|
||||
dns_rdata_soa_t soa;
|
||||
dns_rdata_t *rdata = NULL;
|
||||
dns_rdatalist_t *rdatalist = NULL;
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
dns_name_t *soaname = NULL;
|
||||
|
||||
debug ("insert_soa()");
|
||||
soa.mctx = mctx;
|
||||
soa.serial = lookup->ixfr_serial;
|
||||
soa.refresh = 1;
|
||||
soa.retry = 1;
|
||||
soa.expire = 1;
|
||||
soa.minimum = 1;
|
||||
soa.common.rdclass = dns_rdataclass_in;
|
||||
soa.common.rdtype = dns_rdatatype_soa;
|
||||
|
||||
dns_name_init(&soa.origin, NULL);
|
||||
dns_name_init(&soa.mname, NULL);
|
||||
|
||||
dns_name_clone(lookup->name, &soa.origin);
|
||||
dns_name_clone(lookup->name, &soa.mname);
|
||||
|
||||
isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
|
||||
MXNAME);
|
||||
|
||||
result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
|
||||
check_result(result, "dns_message_gettemprdata");
|
||||
result = dns_rdata_fromstruct(rdata, dns_rdataclass_in,
|
||||
dns_rdatatype_soa, &soa,
|
||||
&lookup->rdatabuf);
|
||||
check_result(result, "isc_rdata_fromstruct");
|
||||
|
||||
result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
|
||||
check_result(result, "dns_message_gettemprdatalist");
|
||||
|
||||
result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
|
||||
check_result(result, "dns_message_gettemprdataset");
|
||||
|
||||
dns_rdatalist_init(rdatalist);
|
||||
rdatalist->type = dns_rdatatype_soa;
|
||||
rdatalist->rdclass = dns_rdataclass_in;
|
||||
rdatalist->covers = dns_rdatatype_soa;
|
||||
rdatalist->ttl = 1;
|
||||
ISC_LIST_INIT(rdatalist->rdata);
|
||||
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
||||
|
||||
dns_rdataset_init(rdataset);
|
||||
dns_rdatalist_tordataset(rdatalist, rdataset);
|
||||
|
||||
result = dns_message_gettempname(lookup->sendmsg, &soaname);
|
||||
check_result(result, "dns_message_gettempname");
|
||||
dns_name_init(soaname, NULL);
|
||||
dns_name_clone(lookup->name, soaname);
|
||||
ISC_LIST_INIT(soaname->list);
|
||||
ISC_LIST_APPEND(soaname->list, rdataset, link);
|
||||
dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
|
||||
}
|
||||
|
||||
void
|
||||
setup_lookup(dig_lookup_t *lookup) {
|
||||
isc_result_t result, res2;
|
||||
|
|
@ -889,8 +952,7 @@ setup_lookup(dig_lookup_t *lookup) {
|
|||
|
||||
dns_message_addname(lookup->sendmsg, lookup->name,
|
||||
DNS_SECTION_QUESTION);
|
||||
|
||||
|
||||
|
||||
if (lookup->trace_root) {
|
||||
tr.base="SOA";
|
||||
tr.length=3;
|
||||
|
|
@ -898,9 +960,11 @@ setup_lookup(dig_lookup_t *lookup) {
|
|||
tr.base=lookup->rttext;
|
||||
tr.length=strlen(lookup->rttext);
|
||||
}
|
||||
debug ("Data type is %s", lookup->rttext);
|
||||
result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr);
|
||||
check_result(result, "dns_rdatatype_fromtext");
|
||||
if (rdtype == dns_rdatatype_axfr) {
|
||||
if ((rdtype == dns_rdatatype_axfr) ||
|
||||
(rdtype == dns_rdatatype_ixfr)) {
|
||||
lookup->doing_xfr = ISC_TRUE;
|
||||
/*
|
||||
* Force TCP mode if we're doing an xfr.
|
||||
|
|
@ -918,6 +982,9 @@ setup_lookup(dig_lookup_t *lookup) {
|
|||
check_result(result, "dns_rdataclass_fromtext");
|
||||
add_type(lookup->sendmsg, lookup->name, rdclass, rdtype);
|
||||
|
||||
if (rdtype == dns_rdatatype_ixfr)
|
||||
insert_soa(lookup);
|
||||
|
||||
isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE);
|
||||
debug ("Starting to render the message");
|
||||
result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf);
|
||||
|
|
@ -928,6 +995,9 @@ setup_lookup(dig_lookup_t *lookup) {
|
|||
result = dns_message_rendersection(lookup->sendmsg,
|
||||
DNS_SECTION_QUESTION, 0);
|
||||
check_result(result, "dns_message_rendersection");
|
||||
result = dns_message_rendersection(lookup->sendmsg,
|
||||
DNS_SECTION_AUTHORITY, 0);
|
||||
check_result(result, "dns_message_rendersection");
|
||||
result = dns_message_renderend(lookup->sendmsg);
|
||||
check_result(result, "dns_message_renderend");
|
||||
debug ("Done rendering.");
|
||||
|
|
@ -951,6 +1021,8 @@ setup_lookup(dig_lookup_t *lookup) {
|
|||
query->waiting_connect = ISC_FALSE;
|
||||
query->first_pass = ISC_TRUE;
|
||||
query->first_soa_rcvd = ISC_FALSE;
|
||||
query->second_rr_rcvd = ISC_FALSE;
|
||||
query->second_rr_serial = 0;
|
||||
query->servname = serv->servername;
|
||||
ISC_LIST_INIT(query->sendlist);
|
||||
ISC_LIST_INIT(query->recvlist);
|
||||
|
|
@ -1292,13 +1364,15 @@ connect_done(isc_task_t *task, isc_event_t *event) {
|
|||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static isc_boolean_t
|
||||
msg_contains_soa(dns_message_t *msg, dig_query_t *query) {
|
||||
isc_result_t result;
|
||||
dns_name_t *name=NULL;
|
||||
|
||||
|
||||
debug("msg_contains_soa()");
|
||||
|
||||
|
||||
result = dns_message_findname(msg, DNS_SECTION_ANSWER,
|
||||
query->lookup->name, dns_rdatatype_soa,
|
||||
0, &name, NULL);
|
||||
|
|
@ -1307,11 +1381,150 @@ msg_contains_soa(dns_message_t *msg, dig_query_t *query) {
|
|||
return (ISC_TRUE);
|
||||
} else {
|
||||
debug("Didn't find SOA, result=%d:%s",
|
||||
result, dns_result_totext(result));
|
||||
result, dns_result_totext(result));
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
check_for_more_data(dig_query_t *query, dns_message_t *msg,
|
||||
isc_socketevent_t *sevent)
|
||||
{
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
dns_rdata_t rdata;
|
||||
dns_rdata_soa_t soa;
|
||||
isc_result_t result;
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
char *abspace[MXNAME];
|
||||
|
||||
debug ("check_for_more_data()");
|
||||
|
||||
/*
|
||||
* By the time we're in this routine, we know we're doing
|
||||
* either an AXFR or IXFR. If there's no second_rr_type,
|
||||
* then we don't yet know which kind of answer we got back
|
||||
* from the server. Here, we're going to walk through the
|
||||
* rr's in the message, acting as necessary whenever we hit
|
||||
* an SOA rr.
|
||||
*/
|
||||
|
||||
result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
|
||||
check_result(result, "dns_message_firstname");
|
||||
do {
|
||||
dns_message_currentname(msg, DNS_SECTION_ANSWER,
|
||||
&name);
|
||||
for (rdataset = ISC_LIST_HEAD(name->list);
|
||||
rdataset != NULL;
|
||||
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
||||
result = dns_rdataset_first(rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
continue;
|
||||
do {
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
/*
|
||||
* If this is the first rr, make sure
|
||||
* it's an SOA
|
||||
*/
|
||||
if ((!query->first_soa_rcvd) &&
|
||||
(rdata.type != dns_rdatatype_soa)) {
|
||||
puts("; Transfer failed. "
|
||||
"Didn't start with "
|
||||
"SOA answer.");
|
||||
query->working = ISC_FALSE;
|
||||
cancel_lookup(query->lookup);
|
||||
return;
|
||||
}
|
||||
if ((!query->second_rr_rcvd) &&
|
||||
(rdata.type != dns_rdatatype_soa)) {
|
||||
query->second_rr_rcvd = ISC_TRUE;
|
||||
query->second_rr_serial = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the record is anything except an SOA
|
||||
* now, just continue on...
|
||||
*/
|
||||
if (rdata.type != dns_rdatatype_soa)
|
||||
goto NEXT_RDATA;
|
||||
/* Now we have an SOA. Work with it. */
|
||||
debug ("before tostruct");
|
||||
result = dns_rdata_tostruct(&rdata,
|
||||
&soa,
|
||||
mctx);
|
||||
check_result(result,
|
||||
"dns_rdata_tostruct");
|
||||
debug ("after tostruct");
|
||||
if (!query->first_soa_rcvd) {
|
||||
query->first_soa_rcvd =
|
||||
ISC_TRUE;
|
||||
query->first_rr_serial =
|
||||
soa.serial;
|
||||
if (query->lookup->ixfr_serial >=
|
||||
soa.serial) {
|
||||
dns_rdata_freestruct(&soa);
|
||||
goto XFR_DONE;
|
||||
}
|
||||
dns_rdata_freestruct(&soa);
|
||||
goto NEXT_RDATA;
|
||||
}
|
||||
if (!query->second_rr_rcvd) {
|
||||
query->second_rr_rcvd = ISC_TRUE;
|
||||
query->second_rr_serial =
|
||||
soa.serial;
|
||||
goto NEXT_RDATA;
|
||||
}
|
||||
if (query->second_rr_serial == 0) {
|
||||
/*
|
||||
* If the second RR was a non-SOA
|
||||
* record, and we're getting any
|
||||
* other SOA, then this is an
|
||||
* AXFR, and we're done.
|
||||
*/
|
||||
XFR_DONE:
|
||||
isc_buffer_init(&b, abspace, MXNAME);
|
||||
result = isc_sockaddr_totext(&sevent->
|
||||
address,
|
||||
&b);
|
||||
check_result(result,
|
||||
"isc_sockaddr_totext");
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
received(b.used, r.length,
|
||||
(char *)r.base, query);
|
||||
query->working = ISC_FALSE;
|
||||
cancel_lookup(query->lookup);
|
||||
dns_rdata_freestruct(&soa);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* If we get to this point, we're doing an
|
||||
* IXFR and have to start really looking
|
||||
* at serial numbers.
|
||||
*/
|
||||
if (query->second_rr_serial == soa.serial) {
|
||||
if (!query->first_repeat_rcvd) {
|
||||
query->first_repeat_rcvd =
|
||||
ISC_TRUE;
|
||||
dns_rdata_freestruct(&soa);
|
||||
goto NEXT_RDATA;
|
||||
}
|
||||
dns_rdata_freestruct(&soa);
|
||||
goto XFR_DONE;
|
||||
}
|
||||
dns_rdata_freestruct(&soa);
|
||||
NEXT_RDATA:
|
||||
result = dns_rdataset_next(rdataset);
|
||||
} while (result == ISC_R_SUCCESS);
|
||||
}
|
||||
result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
|
||||
} while (result == ISC_R_SUCCESS);
|
||||
launch_next_query(query, ISC_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
recv_done(isc_task_t *task, isc_event_t *event) {
|
||||
|
|
@ -1439,42 +1652,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
|
|||
query->waiting_connect = ISC_FALSE;
|
||||
return;
|
||||
}
|
||||
if (!query->first_soa_rcvd) {
|
||||
debug("Not yet got first SOA");
|
||||
if (!msg_contains_soa(msg, query)) {
|
||||
puts("; Transfer failed. "
|
||||
"Didn't start with SOA answer.");
|
||||
query->working = ISC_FALSE;
|
||||
cancel_lookup(query->lookup);
|
||||
dns_message_destroy (&msg);
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
query->first_soa_rcvd = ISC_TRUE;
|
||||
launch_next_query(query, ISC_FALSE);
|
||||
}
|
||||
} else {
|
||||
if (msg_contains_soa(msg, query)) {
|
||||
isc_buffer_init(&ab, abspace, MXNAME);
|
||||
result = isc_sockaddr_totext(&sevent->
|
||||
address,
|
||||
&ab);
|
||||
check_result(result,
|
||||
"isc_sockaddr_totext");
|
||||
isc_buffer_usedregion(&ab, &r);
|
||||
received(b->used, r.length,
|
||||
(char *)r.base, query);
|
||||
query->working = ISC_FALSE;
|
||||
cancel_lookup(query->lookup);
|
||||
dns_message_destroy (&msg);
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
launch_next_query(query, ISC_FALSE);
|
||||
}
|
||||
}
|
||||
check_for_more_data(query, msg, sevent);
|
||||
}
|
||||
else {
|
||||
if ((msg->rcode == 0) ||
|
||||
|
|
|
|||
|
|
@ -657,6 +657,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
|
|||
lookup->xfr_q = NULL;
|
||||
lookup->origin = NULL;
|
||||
lookup->doing_xfr = ISC_FALSE;
|
||||
lookup->ixfr_serial = 0;
|
||||
lookup->defname = ISC_FALSE;
|
||||
lookup->identify = ISC_FALSE;
|
||||
lookup->recurse = recursion;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <isc/mem.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/print.h>
|
||||
#include <dns/rdatalist.h>
|
||||
|
||||
#define MXSERV 4
|
||||
#define MXNAME 256
|
||||
|
|
@ -98,6 +99,9 @@ struct dig_lookup {
|
|||
int retries;
|
||||
int nsfound;
|
||||
isc_uint16_t udpsize;
|
||||
isc_uint32_t ixfr_serial;
|
||||
isc_buffer_t rdatabuf;
|
||||
char rdatastore[MXNAME];
|
||||
};
|
||||
|
||||
struct dig_query {
|
||||
|
|
@ -105,7 +109,11 @@ struct dig_query {
|
|||
isc_boolean_t working,
|
||||
waiting_connect,
|
||||
first_pass,
|
||||
first_soa_rcvd;
|
||||
first_soa_rcvd,
|
||||
second_rr_rcvd,
|
||||
first_repeat_rcvd;
|
||||
isc_uint32_t first_rr_serial;
|
||||
isc_uint32_t second_rr_serial;
|
||||
int retries;
|
||||
char *servname;
|
||||
isc_bufferlist_t sendlist,
|
||||
|
|
|
|||
|
|
@ -642,6 +642,7 @@ addlookup(char *opt) {
|
|||
lookup->origin = NULL;
|
||||
lookup->use_my_server_list = ISC_FALSE;
|
||||
lookup->doing_xfr = ISC_FALSE;
|
||||
lookup->ixfr_serial = 0;
|
||||
lookup->defname = ISC_FALSE;
|
||||
lookup->trace = (trace || ns_search_only);
|
||||
lookup->trace_root = trace;
|
||||
|
|
|
|||
Loading…
Reference in a new issue