/*
* Getzone - Zone transfer client
*
* Copyright (C) Meilof Veeningen, 2003
*/
#include <poslib/poslib.h>
const int tcp_timeout = 5000;
void transfer_zone(_addr a, domainname znroot, FILE *out) {
int sockid = tcpopen(&a), ilen, pos, n, t, l;
DnsMessage *q = create_query(znroot, QTYPE_AXFR);
message_buff buff = q->compile(TCP_MSG_SIZE);
delete q;
char len[2] = { buff.len/256, buff.len };
tcpsendall(sockid, len, 2, tcp_timeout / 4);
tcpsendall(sockid, buff.msg, buff.len, tcp_timeout / 4);
char *msg = NULL;
_domain retdom = NULL;
char *rdata = NULL; uint16_t rdlen;
int soa = 0;
try {
while (soa != 2) {
/* read message */
if (msg) { free(msg); msg = NULL; }
tcpreadall(sockid, len, 2, tcp_timeout / 4);
ilen = len[0] * 256 + len[1];
if (ilen < 12) throw PException("Incomplete answer message");
msg = (char *)malloc(ilen);
tcpreadall(sockid, msg, ilen, tcp_timeout / 4);
buff = message_buff(msg, ilen);
/* interpret it */
if ((msg[3] & 15) != RCODE_NOERROR) throw PException(true, "Erroneous answer: %s", str_rcode(msg[3]&15).c_str());
n = msg[6] * 256 + msg[7];
pos = 12;
for (t = 0; t < n && pos < ilen; t++) {
/* read this RR */
if (retdom) { free(retdom); retdom = NULL; }
if (rdata) { free(rdata); rdata = NULL; }
retdom = dom_uncompress(buff, pos);
pos += dom_comprlen(buff, pos);
if (pos + 10 > ilen) throw PException(true, "Truncated answer message");
l = buff.msg[pos+8] * 256 + buff.msg[pos+9];
if (pos + 10 + l > ilen) throw PException(true, "Truncated answer message");
if (buff.msg[pos] * 256 + buff.msg[pos+1] == DNS_TYPE_SOA) {
soa++;
if (soa == 2) {
/* done! */
break;
}
}
rr_read(buff.msg[pos] * 256 + buff.msg[pos+1], rdata, rdlen, buff, pos + 10, l);
fwrite(uint16_buff(domlen(retdom)) + l + 10, 1, 2, out);
fwrite(retdom, 1, domlen(retdom), out);
fwrite(buff.msg, 1, 10, out);
fwrite(rdata, 1, rdlen, out);
pos += 10 + l;
}
}
} catch (PException p) {
if (msg) free(msg);
if (retdom) free(retdom);
if (rdata) free(rdata);
throw p;
}
if (msg) free(msg);
if (retdom) free(retdom);
if (rdata) free(rdata);
}
int main(int argc, char **argv) {
_addr a;
FILE *f;
if (argc != 4) {
printf("Usage: %s <server> <zone> <file>\n", argv[0]);
return 1;
}
txt_to_addr(&a, argv[1]);
f = try_fopen(argv[3], "w");
if (!f) {
printf("*** Failed to open %s for writing!\n", argv[3]);
return 1;
}
try {
transfer_zone(a, argv[2], f);
} catch (PException p) {
printf("*** Zone transfer failed: %s\n", p.message);
fclose(f);
return 1;
}
fclose(f);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1