aboutsummaryrefslogtreecommitdiff
path: root/eperd/evtdig.c
diff options
context:
space:
mode:
Diffstat (limited to 'eperd/evtdig.c')
-rw-r--r--eperd/evtdig.c976
1 files changed, 673 insertions, 303 deletions
diff --git a/eperd/evtdig.c b/eperd/evtdig.c
index da67a2a..b3813de 100644
--- a/eperd/evtdig.c
+++ b/eperd/evtdig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2013 RIPE NCC <atlas@ripe.net>
+ * Copyright (c) 2011-2014 RIPE NCC <atlas@ripe.net>
* Copyright (c) 2009 Rocco Carbone <ro...@tecsiel.it>
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
@@ -29,15 +29,17 @@
#include <event2/util.h>
#define DQ(str) "\"" #str "\""
#define DQC(str) "\"" #str "\" : "
-#define JS(key, val) fprintf(fh, "\"" #key"\" : \"%s\" , ", val);
-#define JS_NC(key, val) fprintf(fh, "\"" #key"\" : \"%s\" ", val);
-#define JSDOT(key, val) fprintf(fh, "\"" #key"\" : \"%s.\" , ", val);
-#define JS1(key, fmt, val) fprintf(fh, "\"" #key"\" : "#fmt" , ", val);
-#define JD(key, val) fprintf(fh, "\"" #key"\" : %d , ", val);
-#define JD_NC(key, val) fprintf(fh, "\"" #key"\" : %d ", val);
-#define JU(key, val) fprintf(fh, "\"" #key"\" : %u , ", val);
-#define JU_NC(key, val) fprintf(fh, "\"" #key"\" : %u", val);
-#define JC fprintf(fh, ",");
+#define ADDRESULT buf_add(&qry->result, line, strlen(line));
+#define AS(val) buf_add(&qry->result, val, strlen (val));
+#define JS(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : \"%s\" , ", val); ADDRESULT
+#define JS_NC(key, val) snprintf(line, DEFAULT_LINE_LENGTH,"\"" #key"\" : \"%s\" ", val); ADDRESULT
+#define JSDOT(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : \"%s.\" , ", val); ADDRESULT
+#define JS1(key, fmt, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : "#fmt" , ", val); ADDRESULT
+#define JD(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : %d , ", val); ADDRESULT
+#define JD_NC(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : %d ", val); ADDRESULT
+#define JU(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : %u , ", val); ADDRESULT
+#define JU_NC(key, val) snprintf(line, DEFAULT_LINE_LENGTH, "\"" #key"\" : %u", val); ADDRESULT
+#define JC snprintf(line, DEFAULT_LINE_LENGTH, ","); ADDRESULT
#define SAFE_PREFIX ATLAS_DATA_NEW
@@ -46,11 +48,14 @@
#undef MIN /* just in case */
#undef MAX /* also, just in case */
-#define Q_RESOLV_CONF -1
#define O_RESOLV_CONF 1003
#define O_PREPEND_PROBE_ID 1004
#define O_EVDNS 1005
#define O_RETRY 1006
+#define O_TYPE 1007
+#define O_CLASS 1008
+#define O_QUERY 1009
+#define O_OUTPUT_COBINED 1101
#define DNS_FLAG_RD 0x0100
@@ -68,7 +73,7 @@
#define DEFAULT_LINE_LENGTH 80
#define DEFAULT_STATS_REPORT_INTERVEL 180 /* in seconds */
#define CONN_TO 5 /* TCP connection time out in seconds */
-#define DEFAULT_RETRY_MAX 10
+#define DEFAULT_RETRY_MAX 0
/* state of the dns query */
#define STATUS_DNS_RESOLV 1001
@@ -77,9 +82,65 @@
#define STATUS_TCP_WRITE 1004
#define STATUS_NEXT_QUERY 1005
#define STATUS_RETRANSMIT_QUERY 1006
+#define STATUS_PRINT_FREE 1006
+#define STATUS_SEND 1007
+#define STATUS_WAIT_RESPONSE 1008
#define STATUS_FREE 0
-// seems T_DNSKEY is not defined header files of lenny and sdk
+// seems the following are defined in header files we use
+
+#ifndef ns_t_apl
+#define ns_t_apl 42
+#endif
+
+#ifndef T_APL
+#define T_APL ns_t_apl
+#endif
+
+#ifndef ns_t_caa
+#define ns_t_caa 257
+#endif
+
+#ifndef T_CAA
+#define T_CAA ns_t_caa
+#endif
+
+#ifndef ns_t_cert
+#define ns_t_cert 37
+#endif
+
+#ifndef T_CERT
+#define T_CERT ns_t_cert
+#endif
+
+#ifndef ns_t_dname
+#define ns_t_dname 39
+#endif
+
+#ifndef T_DNAME
+#define T_DNAME ns_t_dname
+#endif
+
+
+
+
+#ifndef ns_t_dlv
+#define ns_t_dlv 32769
+#endif
+
+#ifndef T_DLV
+#define T_DLV ns_t_dlv
+#endif
+
+
+#ifndef ns_t_ds
+#define ns_t_ds 43
+#endif
+
+#ifndef T_DS
+#define T_DS ns_t_ds
+#endif
+
#ifndef ns_t_dnskey
#define ns_t_dnskey 48
#endif
@@ -88,6 +149,15 @@
#define T_DNSKEY ns_t_dnskey
#endif
+#ifndef ns_t_ipseckey
+#define ns_t_ipseckey 45
+#endif
+
+#ifndef T_IPSECKEY
+#define T_IPSECKEY ns_t_ipseckey
+#endif
+
+
#ifndef ns_t_rrsig
#define ns_t_rrsig 46
#endif
@@ -104,23 +174,54 @@
#define T_NSEC ns_t_nsec
#endif
+#ifndef ns_t_nsec3
+#define ns_t_nsec3 50
+#endif
+
#ifndef T_NSEC3
#define T_NSEC3 ns_t_nsec3
#endif
-#ifndef ns_t_nsec3
-#define ns_t_nsec3 50
+#ifndef ns_t_nsec3param
+#define ns_t_nsec3param 51
#endif
+#ifndef T_NSEC3PARAM
+#define T_NSEC3PARAM ns_t_nsec3param
+#endif
-#ifndef ns_t_ds
-#define ns_t_ds 43
+#ifndef ns_t_spf
+#define ns_t_spf 99
#endif
-#ifndef T_DS
-#define T_DS ns_t_ds
-#endif
+#ifndef T_SPF
+#define T_SPF ns_t_spf
+#endif
+
+#ifndef ns_t_ta
+#define ns_t_ta 32768
+#endif
+
+#ifndef T_TA
+#define T_TA ns_t_ta
+#endif
+
+#ifndef ns_t_tlsa
+#define ns_t_tlsa 52
+#endif
+#ifndef T_TLSA
+#define T_TLSA ns_t_tlsa
+#endif
+
+
+#ifndef ns_t_sshfp
+#define ns_t_sshfp 44
+#endif
+
+#ifndef T_SSHFP
+#define T_SSHFP ns_t_sshfp
+#endif
/* Definition for various types of counters */
typedef uint32_t counter_t;
@@ -190,8 +291,11 @@ struct query_state {
int opt_rd;
int opt_prepend_probe_id;
int opt_evdns;
+ int opt_rset;
int opt_retry_max;
+ int opt_query_arg;
int retry;
+ int resolv_i;
char * str_Atlas;
u_int16_t qtype;
@@ -210,6 +314,7 @@ struct query_state {
struct event noreply_timer; /* Timer to handle timeout */
struct event nsm_timer; /* Timer to send UDP */
struct event next_qry_timer; /* Timer event to start next query */
+ struct event done_qry_timer; /* Timer event to call done */
struct timeval xmit_time;
double triptime;
@@ -224,6 +329,7 @@ struct query_state {
struct buf err;
struct buf qbuf;
struct buf packet;
+ struct buf result;
int qst ;
char dst_addr_str[(INET6_ADDRSTRLEN+1)];
char loc_addr_str[(INET6_ADDRSTRLEN+1)];
@@ -240,24 +346,36 @@ struct DNS_HEADER
{
u_int16_t id; // identification number
- u_int16_t flags;
-/*
- u_int16_t rd :1, // recursion desired
- tc :1, // truncated message
- aa :1, // authoritive answer
- opcode :4, // purpose of message
- qr :1, // query/response flag
- rcode :4, // response code
- cd :1, // checking disabled
- ad :1, // authenticated data
- z :1, // its z! reserved
- ra :1; // recursion available
-
-*/
- u_int16_t q_count; // number of question entries
- u_int16_t ans_count; // number of answer entries
- u_int16_t ns_count; // number of authority entries
- u_int16_t add_count; // number of resource entries
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int16_t qr :1, /* query/response flag */
+ opcode :4, /* purpose of message */
+ aa :1, /* authoritive answer */
+ tc :1, /* truncated message */
+ rd :1, /* recursion desired */
+
+ ra :1, /* recursion available */
+ z :1, /* its z! reserved */
+ ad :1, /* authenticated data */
+ cd :1, /* checking disabled */
+ rcode :4; /* response code */
+#elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ u_int16_t rd :1,
+ tc :1,
+ aa :1,
+ opcode :4,
+ qr :1,
+
+ rcode :4,
+ cd :1,
+ ad :1,
+ z :1,
+ ra :1;
+#endif
+
+ u_int16_t q_count; /* number of question entries */
+ u_int16_t ans_count; /* number of answer entries */
+ u_int16_t ns_count; /* number of authority entries */
+ u_int16_t add_count; /* number of resource entries */
};
// EDNS OPT pseudo-RR : EDNS0
@@ -310,22 +428,43 @@ static struct option longopts[]=
{
// class IN
{ "a", required_argument, NULL, (100000 + T_A) },
- { "ns", required_argument, NULL, (100000 + T_NS) },
- { "cname", required_argument, NULL, (100000 + T_CNAME) },
- { "ptr", required_argument, NULL, (100000 + T_PTR ) },
- { "mx", required_argument, NULL, (100000 + T_MX ) },
- { "txt", required_argument, NULL, (100000 + T_TXT ) },
{ "aaaa", required_argument, NULL, (100000 + T_AAAA) },
- { "axfr", required_argument, NULL, (100000 + T_AXFR ) }, //yet to be tested.
{ "any", required_argument, NULL, (100000 + T_ANY) },
+ { "afsdb", required_argument, NULL, (100000 + T_AFSDB) },
+ { "apl", required_argument, NULL, (100000 + T_APL) },
+ { "axfr", required_argument, NULL, (100000 + T_AXFR ) }, //yet to be tested.
+ { "caa", required_argument, NULL, (100000 + T_CAA) },
+ { "cert", required_argument, NULL, (100000 + T_CERT) },
+ { "cname", required_argument, NULL, (100000 + T_CNAME) },
+ { "dlv", required_argument, NULL, (100000 + T_DLV) },
+ { "dname", required_argument, NULL, (100000 + T_DNAME) },
{ "dnskey", required_argument, NULL, (100000 + T_DNSKEY) },
+ { "ds", required_argument, NULL, (100000 + T_DS) },
+ { "ipseckey", required_argument, NULL, (100000 + T_IPSECKEY) },
+ { "key", required_argument, NULL, (100000 + T_KEY) },
+ { "loc", required_argument, NULL, (100000 + T_LOC) },
+ { "mx", required_argument, NULL, (100000 + T_MX ) },
+ { "naptr", required_argument, NULL, (100000 + T_NAPTR) },
+ { "ns", required_argument, NULL, (100000 + T_NS) },
{ "nsec", required_argument, NULL, (100000 + T_NSEC) },
{ "nsec3", required_argument, NULL, (100000 + T_NSEC3) },
- { "ds", required_argument, NULL, (100000 + T_DS) },
+ { "nsec3param", required_argument, NULL, (100000 + T_NSEC3PARAM) },
+ { "ptr", required_argument, NULL, (100000 + T_PTR) },
{ "rrsig", required_argument, NULL, (100000 + T_RRSIG) },
+ { "rp", required_argument, NULL, (100000 + T_RP) },
{ "soa", required_argument, NULL, 's' },
+ { "sig", required_argument, NULL, (100000 + T_SIG) },
+ { "spf", required_argument, NULL, (100000 + T_SPF) },
+ { "sshfp", required_argument, NULL, (100000 + T_SSHFP) },
{ "srv", required_argument, NULL, (100000 + T_SRV) },
- { "naptr", required_argument, NULL, (100000 + T_NAPTR) },
+ { "ta", required_argument, NULL, (100000 + T_TA) },
+ { "tlsa", required_argument, NULL, (100000 + T_TLSA) },
+ { "tsig", required_argument, NULL, (100000 + T_TSIG) },
+ { "txt", required_argument, NULL, (100000 + T_TXT) },
+
+ { "type", required_argument, NULL, 'O_TYPE' },
+ { "class", required_argument, NULL, 'O_CLASS' },
+ { "query", required_argument, NULL, O_QUERY},
// clas CHAOS
{ "hostname.bind", no_argument, NULL, 'h' },
@@ -336,7 +475,7 @@ static struct option longopts[]=
// flags
{ "edns0", required_argument, NULL, 'e' },
{ "nsid", no_argument, NULL, 'n' },
- { "d0", no_argument, NULL, 'd' },
+ { "do", no_argument, NULL, 'd' },
{ "retry", required_argument, NULL, O_RETRY },
{ "resolv", no_argument, NULL, O_RESOLV_CONF },
@@ -346,9 +485,11 @@ static struct option longopts[]=
{ "evdns", no_argument, NULL, O_EVDNS },
{ "out-file", required_argument, NULL, 'O' },
{ "p_probe_id", no_argument, NULL, O_PREPEND_PROBE_ID },
+ { "c_output", no_argument, NULL, O_OUTPUT_COBINED},
+
{ NULL, }
};
-static char line[DEFAULT_LINE_LENGTH];
+static char line[(DEFAULT_LINE_LENGTH+1)];
static void tdig_stats(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h);
static int tdig_delete(void *state);
@@ -374,7 +515,7 @@ unsigned char* ReadName(unsigned char *base, size_t size, size_t offset,
int* count);
/* from tdig.c */
-void print_txt_json(unsigned char *rdata, int txt_len, FILE *fh);
+void print_txt_json(unsigned char *rdata, int txt_len,struct query_state *qry);
int evtdig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int evtdig_main(int argc, char **argv)
@@ -411,30 +552,50 @@ int evtdig_main(int argc, char **argv)
return 0;
}
-void print_txt_json(unsigned char *rdata, int txt_len, FILE *fh)
+void print_txt_json(unsigned char *rdata, int txt_len,struct query_state *qry)
{
int i;
- fprintf(fh, ", \"RDATA\" : \"");
+ AS("\"RDATA\" : \"");
for(i = 0; i < txt_len; i++) {
if( (*rdata == 34 ) || (*rdata == 92 )) {
- fprintf(fh, "\\%c", *(char *)rdata );
+ snprintf(line, DEFAULT_LINE_LENGTH, "\\%c", *(char *)rdata );
+ buf_add(&qry->result, line, strlen (line));
}
// Space - DEL
else if ((*rdata > 31 ) && (*rdata < 128)) {
- fprintf(fh, "%c", *(char *)rdata );
+ snprintf(line, DEFAULT_LINE_LENGTH, "%c", *(char *)rdata );
+ buf_add(&qry->result, line, strlen (line));
}
else {
- fprintf(fh, "\\u00%02X", *rdata );
+ snprintf(line, DEFAULT_LINE_LENGTH, "\\u00%02X", *rdata );
+ buf_add(&qry->result, line, strlen (line));
}
rdata++;
}
-
- fprintf(fh, "\"");
+ AS("\"");
}
static void local_exit(void *state UNUSED_PARAM)
{
+ /*
+ qry->base->done(qry);
+ void (*terminator)(void *state);
+ struct event_base *event_base;
+ struct tdig_base *tbase;
+ terminator = qry->base->done;
+ event_base = qry->base->event_base;
+ if (DnsBase) {
+ evdns_base_free(DnsBase, 0);
+ DnsBase = NULL;
+ }
+ tbase = qry->base;
+ tdig_delete(qry);
+ free(tbase);
+ event_base_loopbreak(event_base);
+ event_base_free(event_base);
+ terminator(qry);
+ */
fprintf(stderr, "And we are done\n");
exit(0);
}
@@ -506,8 +667,7 @@ static struct query_state* tdig_lookup_query( struct tdig_base * base, int idx,
i++;
if (qry->qryid == idx)
{
- //AA chnage to LVL5
- crondlog(LVL7 "found matching query id %d", idx);
+ crondlog(LVL5 "found matching query id %d", idx);
if( qry->ressent && ip_addr_cmp (af, remote, qry->ressent->ai_family, qry->ressent->ai_addr) == 0) {
crondlog(LVL7 "matching id and address id %d", idx);
return qry;
@@ -546,7 +706,7 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet)
crondlog(LVL5 "%s %s() : %d base address %p",__FILE__, __func__, __LINE__, qry->base);
BLURT(LVL5 "dns qyery id %d", qry->qryid);
dns->id = (uint16_t) htons(r);
- /*
+
dns->qr = 0; //This is a query
dns->opcode = 0; //This is a standard query
dns->aa = 0; //Not Authoritative
@@ -557,15 +717,14 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet)
dns->ad = 0;
dns->cd = 0;
dns->rcode = 0;
-*/
- dns->q_count = htons(1); //we have only 1 question
+
+ dns->q_count = htons(1); /* we have only 1 question */
dns->ans_count = 0;
dns->ns_count = 0;
dns->add_count = htons(0);
- if (( qry->opt_resolv_conf > Q_RESOLV_CONF ) || (qry->opt_rd )){
- // if you need more falgs do a bitwise and here.
- dns->flags = htons(DNS_FLAG_RD);
+ if (qry->opt_resolv_conf || qry->opt_rd ){
+ dns->rd = 1;
}
//point to the query portion
@@ -659,9 +818,10 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event
int err = 0;
int sockfd;
- /* Clean the no reply timer (if any was previously set) */
+ /* Clean the no reply timer (if any was previously set) */
evtimer_del(&qry->noreply_timer);
+ qry->qst = STATUS_SEND;
outbuff = xzalloc(MAX_DNS_OUT_BUF_SIZE);
bzero(outbuff, MAX_DNS_OUT_BUF_SIZE);
//AA delete qry->outbuff = outbuff;
@@ -723,6 +883,13 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event
printReply (qry, 0, NULL);
return;
}
+ qry->qst = STATUS_WAIT_RESPONSE;
+}
+static void done_qry_cb(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h) {
+ struct query_state *qry = h;
+ qry->qst = STATUS_FREE;
+ BLURT(LVL5 "query %s is done call done", qry->server_name);
+ qry->base->done(qry);
}
static void next_qry_cb(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h) {
@@ -734,7 +901,7 @@ static void next_qry_cb(int unused UNUSED_PARAM, const short event UNUSED_PARAM
/* The callback to handle timeouts due to destination host unreachable condition */
static void noreply_callback(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h)
{
- struct timeval asap = { 0, 0 };
+ struct timeval asap = { 1, 1 };
struct query_state *qry = h;
qry->base->timeout++;
snprintf(line, DEFAULT_LINE_LENGTH, "%s \"timeout\" : %d", qry->err.size ? ", " : "", DEFAULT_NOREPLY_TIMEOUT);
@@ -743,8 +910,8 @@ static void noreply_callback(int unused UNUSED_PARAM, const short event UNUSED_
BLURT(LVL5 "AAA timeout for %s retry %d/%d ", qry->server_name, qry->retry, qry->opt_retry_max);
if (qry->retry < qry->opt_retry_max) {
qry->retry++;
- free_qry_inst(qry);
qry->qst = STATUS_RETRANSMIT_QUERY;
+ free_qry_inst(qry);
evtimer_add(&qry->next_qry_timer, &asap);
} else {
printReply (qry, 0, NULL);
@@ -804,8 +971,8 @@ static void tcp_reporterr(struct tu_env *env, enum tu_err cause,
}
if (qry->retry < qry->opt_retry_max) {
qry->retry++;
- free_qry_inst(qry);
qry->qst = STATUS_RETRANSMIT_QUERY;
+ free_qry_inst(qry);
evtimer_add(&qry->next_qry_timer, &asap);
} else {
printReply (qry, 0, NULL);
@@ -816,6 +983,7 @@ static void tcp_dnscount(struct tu_env *env, int count)
{
struct query_state * qry;
qry = ENV2QRY(env);
+ qry->qst = STATUS_SEND;
BLURT(LVL5 "dns count for %s : %d", qry->server_name , count);
}
@@ -1042,6 +1210,52 @@ static void ready_callback6 (int unused UNUSED_PARAM, const short event UNUSED_P
return;
}
+static bool argProcess (int argc, char *argv[], struct query_state *qry )
+{
+ if( qry->opt_resolv_conf) {
+ qry->resolv_i = 0;
+ get_local_resolvers(tdig_base->nslist, &tdig_base->resolv_max);
+ if(tdig_base->resolv_max ) {
+ qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
+ }
+ }
+ else if (optind != argc-1) {
+ crondlog(LVL9 "ERROR no server IP address in input");
+ tdig_delete(qry);
+ return TRUE;
+ }
+ else
+ qry->server_name = strdup(argv[optind]);
+
+ if (qry->lookupname == NULL) {
+ crondlog(LVL9 "ERROR no query in command line");
+ tdig_delete(qry);
+ return TRUE;
+ }
+
+ if (qry->lookupname[strlen(qry->lookupname) - 1] != '.') {
+ crondlog(LVL9 "ERROR query %s does not end with a dot ", qry->lookupname);
+ tdig_delete(qry);
+ return TRUE;
+ }
+
+ if (qry->out_filename &&
+ !validate_filename(qry->out_filename, SAFE_PREFIX))
+ {
+ crondlog(LVL8 "insecure file '%s'", qry->out_filename);
+ tdig_delete(qry);
+ return TRUE;
+ }
+
+
+ if(qry->opt_v6_only == 0)
+ {
+ qry->opt_v4_only = 1;
+ qry->opt_AF = AF_INET;
+ }
+ return FALSE;
+}
+
/* this called for each query/line in eperd */
static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
{
@@ -1049,11 +1263,13 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
struct query_state *qry;
int c;
- if(!tdig_base)
+ if (!tdig_base)
tdig_base = tdig_base_new(EventBase);
- if(!tdig_base)
- crondlog(DIE9 "tdig_base_new failed");
+ if (!tdig_base) {
+ crondlog(LVL8 "tdig_base_new failed");
+ return NULL;
+ }
tdig_base->done = done;
@@ -1072,8 +1288,9 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->server_name = NULL;
qry->str_Atlas = NULL;
tdig_base->activeqry++;
- qry->qst = 0;
+ qry->qst = STATUS_FREE;
qry->retry = 0;
+ qry->resolv_i = 0;
qry->opt_retry_max = DEFAULT_RETRY_MAX;
qry->wire_size = 0;
qry->triptime = 0;
@@ -1084,16 +1301,20 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->opt_abuf = 1;
qry->opt_rd = 0;
qry->opt_evdns = 0;
+ qry->opt_rset = 0;
qry->opt_prepend_probe_id = 0;
qry->ressave = NULL;
qry->ressent = NULL;
buf_init(&qry->err, -1);
buf_init(&qry->packet, -1);
- qry->opt_resolv_conf = (Q_RESOLV_CONF - 1);
+ qry->opt_resolv_conf = 0;
qry->lookupname = NULL;
qry->dst_ai_family = 0;
qry->loc_ai_family = 0;
qry->loc_sin6.sin6_family = 0;
+ qry->result.offset = qry->result.size = qry->result.maxsize= 0;
+ qry->result.buf = NULL;
+ qry->opt_query_arg = 0;
/* initialize callbacks : */
/* sendpacket called by UDP send */
@@ -1103,9 +1324,9 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
evtimer_assign(&qry->noreply_timer, tdig_base->event_base,
noreply_callback, qry);
- /* callback/timer used for restarting query by --resove */
- evtimer_assign(&qry->next_qry_timer, tdig_base->event_base, next_qry_cb
- ,qry);
+ /* callback/timer used for restarting query by --resolve */
+ evtimer_assign(&qry->next_qry_timer, tdig_base->event_base, next_qry_cb, qry);
+ evtimer_assign(&qry->done_qry_timer, tdig_base->event_base, done_qry_cb, qry);
optind = 0;
while (c= getopt_long(argc, argv, "46adD:e:tbhinqO:Rrs:A:?", longopts, NULL), c != -1) {
@@ -1188,14 +1409,54 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->opt_abuf = 0;
break;
+ case 'O_TYPE':
+ qry->qtype = strtoul(optarg, &check, 10);
+ if ((qry->qtype >= 0 ) &&
+ (qry->qclass < 65536)) {
+
+ if (! qry->qclass )
+ qry->qclass = C_IN;
+
+ break;
+ }
+ else {
+ fprintf(stderr, "ERROR unknown Q "
+ "--typae %s ??. 0 - "
+ "65535\n", optarg);
+ tdig_delete(qry);
+ return (0);
+ }
+ break;
+
+ case 'O_CLASS':
+ qry->qclass = strtoul(optarg, &check, 10);
+ if ((qry->qclass >= 0 ) &&
+ (qry->qclass < 65536)) {
+ break;
+ }
+ else {
+ fprintf(stderr, "ERROR unknown Q class"
+ " --class %s ??. 0 - "
+ "65535\n", optarg);
+ tdig_delete(qry);
+ return (0);
+ }
+
case O_RETRY :
+ qry->opt_query_arg = 1;
qry->opt_retry_max = strtoul(optarg, NULL, 10);
break;
+ case O_QUERY:
+ qry->opt_query_arg = 1;
+ qry->lookupname = strdup(optarg);
+ break;
+
case O_RESOLV_CONF :
- qry->opt_resolv_conf = Q_RESOLV_CONF ;
+ qry->opt_resolv_conf = 1;
qry->opt_v6_only = 1;
qry->opt_v4_only = 1;
+ qry->opt_rset = 1;
break;
case O_PREPEND_PROBE_ID:
@@ -1212,50 +1473,68 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_NS):
- qry->qtype = T_NS;
+ case (100000 + T_AAAA ):
+ qry->qtype = T_AAAA ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_CNAME):
- qry->qtype = T_CNAME;
+ case (100000 + T_AFSDB ):
+ qry->qtype = T_AFSDB ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_PTR):
- qry->qtype = T_PTR;
+ case (100000 + T_ANY):
+ qry->qtype = T_ANY ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_MX):
- qry->qtype = T_MX;
+ case (100000 + T_APL):
+ qry->qtype = T_APL ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_TXT):
- qry->qtype = T_TXT;
+ case (100000 + T_AXFR ):
+ qry->qtype = T_AXFR ;
qry->qclass = C_IN;
- qry->lookupname = strdup(optarg);
+ qry->lookupname = strdup(optarg);
break;
- case (100000 + T_AAAA ):
- qry->qtype = T_AAAA ;
+ case (100000 + T_CAA):
+ qry->qtype = T_CAA ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_AXFR ):
- qry->qtype = T_AXFR ;
+ case (100000 + T_CERT):
+ qry->qtype = T_CERT ;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_ANY):
- qry->qtype = T_ANY ;
+ case (100000 + T_CNAME):
+ qry->qtype = T_CNAME;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_DLV):
+ qry->qtype = T_DLV;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_DNAME):
+ qry->qtype = T_DNAME;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_DNSKEY):
+ qry->qtype = T_DNSKEY;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
@@ -1266,6 +1545,36 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->lookupname = strdup(optarg);
break;
+ case (100000 + T_IPSECKEY):
+ qry->qtype = T_IPSECKEY;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_LOC):
+ qry->qtype = T_LOC;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_MX):
+ qry->qtype = T_MX;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_NAPTR):
+ qry->qtype = T_NAPTR;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_NS):
+ qry->qtype = T_NS;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
case (100000 + T_NSEC):
qry->qtype = T_NSEC;
qry->qclass = C_IN;
@@ -1278,8 +1587,14 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_DNSKEY):
- qry->qtype = T_DNSKEY;
+ case (100000 + T_NSEC3PARAM):
+ qry->qtype = T_NSEC3PARAM;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_PTR):
+ qry->qtype = T_PTR;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
@@ -1290,79 +1605,71 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->lookupname = strdup(optarg);
break;
+ case (100000 + T_RP):
+ qry->qtype = T_RP;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_SIG):
+ qry->qtype = T_SIG;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
+ case (100000 + T_SPF):
+ qry->qtype = T_SPF;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+
case (100000 + T_SRV):
qry->qtype = T_SRV;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- case (100000 + T_NAPTR):
- qry->qtype = T_NAPTR;
+ case (100000 + T_SSHFP):
+ qry->qtype = T_SSHFP;
qry->qclass = C_IN;
qry->lookupname = strdup(optarg);
break;
- default:
- fprintf(stderr, "ERROR unknown option %d ??\n", c);
- tdig_delete(qry);
- return (0);
+ case (100000 + T_TA):
+ qry->qtype = T_TA;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
break;
- }
- }
- if( qry->opt_resolv_conf == Q_RESOLV_CONF ) {
- if(tdig_base->resolv_max ) {
- qry->opt_resolv_conf = 1;
- qry->server_name = strdup(tdig_base->nslist[0]);
- }
- else {
- // may be the /etc/resolv.conf is yet to red.
- // try once then use it || give up
- tdig_base->resolv_max = get_local_resolvers (tdig_base->nslist);
- if(tdig_base->resolv_max ){
- qry->opt_resolv_conf = 1;
- qry->server_name = strdup(tdig_base->nslist[0]);
- }
- else {
- tdig_delete(qry);
- return NULL;
- }
- }
- }
- else if (optind != argc-1) {
- crondlog(LVL9 "ERROR no server IP address in input");
- tdig_delete(qry);
- return NULL;
- }
- else
- qry->server_name = strdup(argv[optind]);
- if (qry->lookupname == NULL) {
- crondlog(LVL9 "ERROR no query in command line");
- tdig_delete(qry);
- return NULL;
- }
+ case (100000 + T_TLSA):
+ qry->qtype = T_TLSA;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
- if (qry->lookupname[strlen(qry->lookupname) - 1] != '.') {
- crondlog(LVL9 "ERROR query %s does not end with a dot ", qry->lookupname);
- tdig_delete(qry);
- return NULL;
- }
+ case (100000 + T_TSIG):
+ qry->qtype = T_TSIG;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
+ case (100000 + T_TXT):
+ qry->qtype = T_TXT;
+ qry->qclass = C_IN;
+ qry->lookupname = strdup(optarg);
+ break;
- if (qry->out_filename &&
- !validate_filename(qry->out_filename, SAFE_PREFIX))
- {
- crondlog(LVL8 "insecure file '%s'", qry->out_filename);
- tdig_delete(qry);
- return NULL;
+ default:
+ fprintf(stderr, "ERROR unknown option %d ??\n", c);
+ tdig_delete(qry);
+ return (0);
+ break;
+ }
}
+ if(argProcess(argc, argv, qry))
+ return NULL;
- if(qry->opt_v6_only == 0)
- {
- qry->opt_v4_only = 1;
- qry->opt_AF = AF_INET;
- }
qry->base = tdig_base;
/* insert this qry into the list of queries */
@@ -1385,9 +1692,13 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
crondlog(LVL7 " qry %s qry->prev %s qry->next %s", qry->str_Atlas, qry->prev->str_Atlas, qry->next->str_Atlas);
crondlog(LVL7 "new head hea %s hea->prev %s hea->next %s", tdig_base->qry_head->str_Atlas, tdig_base->qry_head->prev->str_Atlas, tdig_base->qry_head->next->str_Atlas);
}
+
return qry;
}
+
+
+
/* called only once. Initialize tdig_base variables here */
struct tdig_base * tdig_base_new(struct event_base *event_base)
{
@@ -1475,10 +1786,10 @@ struct tdig_base * tdig_base_new(struct event_base *event_base)
}
static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, struct query_state *qry) {
-
if (err) {
- qry->qst = STATUS_FREE;
- snprintf(line, DEFAULT_LINE_LENGTH, "\"evdns_getaddrinfo\": \"%s\"", evutil_gai_strerror(err));
+ snprintf(line, DEFAULT_LINE_LENGTH, "\"evdns_getaddrinfo\": "
+ "\"%s %s\"", qry->server_name,
+ evutil_gai_strerror(err));
buf_add(&qry->err, line, strlen(line));
printReply (qry, 0, NULL);
return ;
@@ -1487,6 +1798,7 @@ static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, struct query_sta
else {
qry->res = ev_res;
qry->ressave = ev_res;
+ qry->qst = STATUS_SEND;
tdig_send_query_callback(0, 0, qry);
}
}
@@ -1503,8 +1815,27 @@ void tdig_start (struct query_state *qry)
switch(qry->qst)
{
- case STATUS_NEXT_QUERY :
case STATUS_FREE :
+ qry->resolv_i = 0;
+ crondlog(LVL5 "RESOLV QUERY FREE %s resolv_max %d", qry->server_name, tdig_base->resolv_max);
+ if( qry->opt_resolv_conf) {
+ get_local_resolvers (tdig_base->nslist, &tdig_base->resolv_max);
+ crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max %d %d", qry->server_name, tdig_base->resolv_max, qry->resolv_i);
+ if(tdig_base->resolv_max ) {
+ qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
+ }
+ else {
+ crondlog(LVL5 "AAA RESOLV QUERY FREE %s resolv_max is zero %d i %d", qry->server_name, tdig_base->resolv_max, qry->resolv_i);
+ free(qry->server_name);
+ qry->server_name = NULL;
+ snprintf(line, DEFAULT_LINE_LENGTH, "\"nameserver\": \"no local resolvers found\"");
+ buf_add(&qry->err, line, strlen(line));
+ printReply (qry, 0, NULL);
+ }
+ }
+ break;
+
+ case STATUS_NEXT_QUERY :
case STATUS_RETRANSMIT_QUERY:
break;
default:
@@ -1512,13 +1843,6 @@ void tdig_start (struct query_state *qry)
return ;
}
- if(qry->opt_resolv_conf > tdig_base->resolv_max) {
- qry->opt_resolv_conf = 0;
- free (qry->server_name);
- qry->server_name = strdup(tdig_base->nslist[qry->opt_resolv_conf]);
- qry->opt_resolv_conf++;
- }
-
bzero(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = 0;
@@ -1553,9 +1877,7 @@ void tdig_start (struct query_state *qry)
{
snprintf(line, DEFAULT_LINE_LENGTH, "%s \"getaddrinfo\": \"port %s, AF %d %s\"", qry->err.size ? ", " : "", port, hints.ai_family, gai_strerror(err_num));
buf_add(&qry->err, line, strlen(line));
-
printReply (qry, 0, NULL);
- qry->qst = STATUS_FREE;
return ;
}
@@ -1563,6 +1885,7 @@ void tdig_start (struct query_state *qry)
qry->ressave = res;
evtimer_add(&qry->nsm_timer, &asap);
+ qry->qst = STATUS_SEND;
}
}
else { // TCP Query
@@ -1604,27 +1927,43 @@ static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_
struct timeval now;
FILE *fh;
struct tdig_base *base;
+ struct query_state *qry_h;
+ u_int32_t fw;
struct query_state *qry;
base = h;
if(!base->qry_head )
return;
- qry = base->qry_head;
+ qry_h = base->qry_head;
if(! base->sentok )
return;
- if (qry->out_filename) {
- fh= fopen(qry->out_filename, "a");
- if (!fh)
- crondlog(DIE9 "unable to append to '%s'", qry->out_filename);
+
+ if(qry_h->base->done) {
+ now.tv_sec = DEFAULT_STATS_REPORT_INTERVEL;
+ now.tv_usec = 0;
+ event_add(&tdig_base->statsReportEvent, &now);
+ return;
+ }
+
+ if (qry_h->out_filename) {
+ fh= fopen(qry_h->out_filename, "a");
+ if (!fh) {
+ crondlog(LVL8 "unable to append to '%s'", qry_h->out_filename);
+ return;
+ }
}
else
fh = stdout;
- fprintf(fh, "RESULT { ");
+ qry=xzalloc(sizeof(*qry));
+
+ AS("RESULT { ");
JS(id, "9201" );
+ fw = get_atlas_fw_version();
+ JU(fw, fw);
gettimeofday(&now, NULL);
JS1(time, %ld, now.tv_sec);
JU(sok , base->sentok);
@@ -1638,9 +1977,14 @@ static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_
JU(martian, base->martian);
JU_NC(q, base->activeqry);
- fprintf(fh, " }\n");
- if (qry->out_filename)
+ AS(" }\n");
+ fwrite(qry->result.buf, qry->result.size, 1 , fh);
+ if (qry_h->out_filename)
fclose (fh);
+
+ buf_cleanup(&qry->result);
+ free(qry);
+
// reuse timeval now
now.tv_sec = DEFAULT_STATS_REPORT_INTERVEL;
now.tv_usec = 0;
@@ -1670,7 +2014,7 @@ static void ChangetoDnsNameFormat(u_char * dns, char* qry)
static void free_qry_inst(struct query_state *qry)
{
- struct timeval asap = { 0, 0 };
+ struct timeval asap = { 1, 0 };
BLURT(LVL5 "freeing instance of %s ", qry->server_name);
if(qry->err.size)
@@ -1691,7 +2035,6 @@ static void free_qry_inst(struct query_state *qry)
qry->ressave = NULL;
qry->ressent = NULL;
}
- qry->qst = STATUS_FREE;
qry->wire_size = 0;
if(qry->packet.size)
@@ -1702,43 +2045,32 @@ static void free_qry_inst(struct query_state *qry)
if(qry->opt_proto == 6)
tu_cleanup(&qry->tu_env);
- if ( qry->opt_resolv_conf > Q_RESOLV_CONF ) {
+ if ( qry->opt_resolv_conf) {
// this loop goes over servers in /etc/resolv.conf
// select the next server and restart
- if(qry->opt_resolv_conf < tdig_base->resolv_max) {
- free (qry->server_name);
- qry->server_name = strdup(tdig_base->nslist[qry->opt_resolv_conf]);
- qry->opt_resolv_conf++;
+ if(qry->resolv_i < tdig_base->resolv_max) {
+ if(qry->server_name) {
+ free (qry->server_name);
+ qry->server_name = NULL;
+ }
+ qry->server_name = strdup(tdig_base->nslist[qry->resolv_i]);
qry->qst = STATUS_NEXT_QUERY;
evtimer_add(&qry->next_qry_timer, &asap);
return;
}
- else
- qry->opt_resolv_conf++;
}
- if(qry->base->done)
- {
- qry->base->done(qry);
- /*
- void (*terminator)(void *state);
- struct event_base *event_base;
- struct tdig_base *tbase;
- terminator = qry->base->done;
- event_base = qry->base->event_base;
- if(DnsBase) {
- evdns_base_free(DnsBase, 0);
- DnsBase = NULL;
- }
- tbase = qry->base;
- tdig_delete(qry);
- free(tbase);
- event_base_loopbreak(event_base);
- event_base_free(event_base);
- terminator(qry);
- */
+ switch(qry->qst){
+ case STATUS_RETRANSMIT_QUERY:
+ break;
+
+ default:
+ qry->qst = STATUS_FREE;
+ if(qry->base->done) {
+ evtimer_add(&qry->done_qry_timer, &asap);
+ }
+ break;
}
-
}
@@ -1810,75 +2142,89 @@ void printErrorQuick (struct query_state *qry)
if (qry->out_filename)
{
fh= fopen(qry->out_filename, "a");
- if (!fh)
- crondlog(DIE9 "unable to append to '%s'",
+ if (!fh){
+ crondlog(LVL8 "unable to append to '%s'",
qry->out_filename);
+ return;
+ }
}
else
fh = stdout;
fprintf(fh, "RESULT { ");
-
- JS(id, "9202");
+ fprintf(fh, "\"fw\" : \"%d\",", get_atlas_fw_version());
+ fprintf(fh, "\"id\" : 9202 ,");
gettimeofday(&now, NULL);
- JS1(time, %ld, now.tv_sec);
+ fprintf(fh, "\"time\" : %ld ,", now.tv_sec);
- snprintf(line, DEFAULT_LINE_LENGTH, "\"query busy\": \"too frequent."
- "previous one is not done yet\"");
- fprintf(fh, "\"error\" : [{ %s }" , line);
+ fprintf(fh, "\"error\" : [{ ");
+ fprintf(fh, "\"query busy\": \"not starting a new one. previous one is not done yet\"}");
if(qry->str_Atlas)
{
- fprintf(fh, ",{" , line);
- JS_NC(id, qry->str_Atlas);
- fprintf(fh, "}" , line);
+ fprintf(fh, ",{");
+ fprintf(fh, "\"id\" : \"%s\"", qry->str_Atlas);
+ fprintf(fh, ",\"start time\" : %ld", qry->xmit_time.tv_sec);
+ if(qry->retry) {
+ fprintf(fh, ",\"retry\": %d", qry->retry);
+
+ }
+ if(qry->opt_retry_max) {
+ fprintf(fh, ",\"retry max\": %d", qry->opt_retry_max);
+ }
+ fprintf(fh, "}");
}
- fprintf(fh, "]");
+ fprintf(fh,"]}");
- fprintf(fh, " }");
fprintf(fh, "\n");
if (qry->out_filename)
fclose(fh);
}
-
-void printReply(struct query_state *qry, int wire_size, unsigned char *result )
+void printReply(struct query_state *qry, int wire_size, unsigned char *result)
{
int i, stop=0;
unsigned char *qname, *reader;
struct DNS_HEADER *dnsR = NULL;
struct RES_RECORD answers[20]; //the replies from the DNS server
void *ptr = NULL;
- char addrstr[100];
FILE *fh;
- //char buf[INET6_ADDRSTRLEN];
+ char addrstr[INET6_ADDRSTRLEN];
u_int32_t serial;
- struct buf tmpbuf;
- char str[4];
int iMax ;
- int flagAnswer = 1;
+ int flagAnswer = 0;
int data_len;
+ int write_out = FALSE;
+ u_int32_t fw;
- if (qry->out_filename)
- {
- fh= fopen(qry->out_filename, "a");
- if (!fh)
- crondlog(DIE9 "unable to append to '%s'",
- qry->out_filename);
- }
- else
- fh = stdout;
+ if(! qry->result.size){
+ buf_init(&qry->result, -1);
- fprintf(fh, "RESULT { ");
- if(qry->str_Atlas)
- {
- JS(id, qry->str_Atlas);
+ AS("RESULT { ");
+
+ if(qry->str_Atlas)
+ {
+ JS(id, qry->str_Atlas);
+ }
+
+ fw = get_atlas_fw_version();
+ JU(fw, fw);
+
+ if (qry->opt_rset){
+ JS1(time, %ld, qry->xmit_time.tv_sec);
+ AS("\"resultset\" : [ {");
+ }
+ }
+ else if(qry->opt_rset) {
+ AS (",{");
}
+
JS1(time, %ld, qry->xmit_time.tv_sec);
- if ( qry->opt_resolv_conf > Q_RESOLV_CONF ) {
- JD (subid, qry->opt_resolv_conf);
+ if ( qry->opt_resolv_conf ) {
+ JD (subid, (qry->resolv_i+1));
JD (submax, qry->base->resolv_max);
}
- if( qry->ressent)
+
+ if( qry->ressent && qry->server_name)
{ // started to send query
// historic resaons only works with UDP
switch (qry->ressent->ai_family)
@@ -1890,14 +2236,14 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
ptr = &((struct sockaddr_in6 *) qry->ressent->ai_addr)->sin6_addr;
break;
}
- inet_ntop (qry->ressent->ai_family, ptr, addrstr, 100);
+ inet_ntop (qry->ressent->ai_family, ptr, addrstr, INET6_ADDRSTRLEN);
if(strcmp(addrstr, qry->server_name)) {
JS(name, qry->server_name);
}
JS(dst_addr, addrstr);
JD(af, qry->ressent->ai_family == PF_INET6 ? 6 : 4);
}
- else if(qry->dst_ai_family)
+ else if(qry->dst_ai_family && qry->server_name)
{
if(strcmp(qry->dst_addr_str, qry->server_name)) {
JS(dst_name, qry->server_name);
@@ -1905,27 +2251,28 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
JS(dst_addr , qry->dst_addr_str);
JD(af, qry->dst_ai_family == PF_INET6 ? 6 : 4);
}
- else {
- JS(dst_name, qry->server_name);
+ else if(qry->server_name) {
+ JS(dst_name, qry->server_name);
}
+
if(qry->loc_sin6.sin6_family) {
- line[0] = '\0';
getnameinfo((struct sockaddr *)&qry->loc_sin6,
- qry->loc_socklen, line, sizeof(line),
+ qry->loc_socklen, addrstr, INET6_ADDRSTRLEN,
NULL, 0, NI_NUMERICHOST);
- if(strlen(line))
- JS(src_addr, line);
+ if(strlen(addrstr))
+ JS(src_addr, addrstr);
}
+
if(qry->retry) {
JS1(retry, %d, qry->retry);
}
JS_NC(proto, qry->opt_proto == 6 ? "TCP" : "UDP" );
+
if(qry->opt_qbuf && qry->qbuf.size) {
- str[0] = '\0';
- buf_add(&qry->qbuf, str, 1);
- JC;
- JS_NC(qbuf, qry->qbuf.buf );
+ AS(",\"qbuf\" : \"");
+ buf_add(&qry->result, qry->qbuf.buf, qry->qbuf.size);
+ AS("\" ");
}
if(result)
@@ -1938,28 +2285,26 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
//move ahead of the dns header and the query field
reader = &result[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)];
- fprintf (fh, ", \"result\" : { ");
- fprintf (fh, " \"rt\" : %.3f", qry->triptime);
- fprintf (fh, " , \"size\" : %d", wire_size);
- fprintf (fh, " , \"ID\" : %d", ntohs(dnsR->id));
+ snprintf(line, DEFAULT_LINE_LENGTH, ",\"result\" : { \"rt\" : %.3f,", qry->triptime);
+ buf_add(&qry->result,line, strlen(line));
+
+ JD (size, wire_size);
+ JU (ID, ntohs(dnsR->id));
/*
fprintf (fh, " , \"RCODE\" : %d", dnsR->rcode);
fprintf (fh, " , \"AA\" : %d", dnsR->aa);
fprintf (fh, " , \"TC\" : %d", dnsR->tc);
*/
- fprintf (fh, " , \"ANCOUNT\" : %d ", ntohs(dnsR->ans_count ));
- fprintf (fh, " , \"QDCOUNT\" : %u ",ntohs(dnsR->q_count));
- fprintf (fh, " , \"NSCOUNT\" : %d" , ntohs(dnsR->ns_count));
- fprintf (fh, " , \"ARCOUNT\" : %d ",ntohs(dnsR->add_count));
+ JU (ANCOUNT, ntohs(dnsR->ans_count ));
+ JU (QDCOUNT, ntohs(dnsR->q_count));
+ JU (NSCOUNT, ntohs(dnsR->ns_count));
+ JU_NC (ARCOUNT, ntohs(dnsR->add_count));
- str[0] = '\0';
if(qry->opt_abuf) {
- JC;
- buf_init(&tmpbuf, -1);
- buf_add_b64(&tmpbuf, result, wire_size, 0);
- buf_add(&tmpbuf, str, 1);
- JS_NC(abuf, tmpbuf.buf );
- buf_cleanup(&tmpbuf);
+ snprintf(line, DEFAULT_LINE_LENGTH, ",\"abuf\" : \"");
+ buf_add(&qry->result,line, strlen(line));
+ buf_add_b64(&qry->result, result, wire_size, 0);
+ AS("\"");
}
stop=0;
@@ -1980,42 +2325,34 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
answers[i].rdata = NULL;
-
if(ntohs(answers[i].resource->type)==T_TXT) //txt
{
- answers[i].rdata = NULL;
data_len = ntohs(answers[i].resource->data_len) - 1;
-
- if(flagAnswer) {
- fprintf (fh, ", \"answers\" : [ ");
- flagAnswer = 0;
+ if(flagAnswer == 0) {
+ AS(",\"answers\" : [ {");
+ flagAnswer++;
}
- if (flagAnswer == 0) {
- if(i > 0)
- fprintf(fh, ", ");
- fprintf(fh, " { ");
+ else if (flagAnswer > 0) {
+ AS(", {");
}
- fprintf(fh, " \"TYPE\" : \"TXT\"");
- fprintf(fh, " , \"NAME\" : \"%s.\" ",answers[i].name);
- print_txt_json(&result[reader-result+1], data_len, fh);
+ flagAnswer++;
+ JS (TYPE, "TXT");
+ JS (NAME, answers[i].name);
+ print_txt_json(&result[reader-result+1], data_len, qry);
reader = reader + ntohs(answers[i].resource->data_len);
- if(flagAnswer == 0)
- fprintf(fh, " } ");
+ AS("}");
}
else if (ntohs(answers[i].resource->type)== T_SOA)
{
- if(flagAnswer) {
- fprintf (fh, ", \"answers\" : [ ");
- flagAnswer = 0;
+ if(flagAnswer == 0) {
+ AS(",\"answers\" : [ { ");
}
- if (flagAnswer == 0) {
- if(i > 0)
- fprintf(fh, ", ");
- fprintf(fh, " { ");
+ else if (flagAnswer > 0) {
+ AS(",{ ");
}
+ flagAnswer++;
-
JS(TYPE, "SOA");
JSDOT(NAME, answers[i].name);
JU(TTL, ntohl(answers[i].resource->ttl));
@@ -2034,23 +2371,19 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
JU_NC(SERIAL, serial);
reader = reader + 4;
reader = reader + 16; // skip REFRESH, RETRY, EXIPIRE, and MINIMUM
- if(flagAnswer == 0)
- fprintf(fh, " } ");
+ AS(" } ");
}
else
{
- // JU(TYPE, ntohs(answers[i].resource->type));
- // JU_NC(RDLENGTH, ntohs(answers[i].resource->data_len))
reader = reader + ntohs(answers[i].resource->data_len);
}
- fflush(fh);
// free mem
if(answers[i].rdata != NULL)
free (answers[i].rdata);
}
- if(flagAnswer == 0)
- fprintf (fh, " ]");
+ if(flagAnswer > 0)
+ AS(" ]");
}
for(i=0;i<iMax;i++)
@@ -2058,18 +2391,55 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result )
free(answers[i].name);
}
- fprintf (fh , " }"); //result
+ AS (" }"); //result {
}
if(qry->err.size)
{
- line[0] = '\0';
- buf_add(&qry->err, line, 1 );
- fprintf(fh, ", \"error\" : { %s }" , qry->err.buf);
+ AS(", \"error\" : {");
+ buf_add(&qry->result,qry->err.buf, qry->err.size);
+ AS("}");
+ }
+
+ /* end of result only JSON closing brackets from here on */
+
+ if(qry->opt_rset) {
+ AS("}"); /* resultset : [{ } */
+ }
+ else {
+ write_out = TRUE;
+ }
+
+ if(qry->opt_resolv_conf){
+ qry->resolv_i++;
+
+ if(qry->resolv_i >= tdig_base->resolv_max) {
+ write_out = TRUE;
+ if(qry->opt_rset) {
+ AS ("]"); /* reseultset : [{}] */
+ }
+ }
+ }
+
+ if(write_out && qry->result.size){
+ if (qry->out_filename)
+ {
+ fh= fopen(qry->out_filename, "a");
+ if (!fh) {
+ crondlog(LVL8 "unable to append to '%s'",
+ qry->out_filename);
+ }
+ }
+ else
+ fh = stdout;
+ if (fh) {
+ AS (" }\n"); /* RESULT { } */
+ fwrite(qry->result.buf, qry->result.size, 1 , fh);
+ }
+ buf_cleanup(&qry->result);
+
+ if (qry->out_filename)
+ fclose(fh);
}
- fprintf(fh, " }");
- fprintf(fh, "\n");
- if (qry->out_filename)
- fclose(fh);
qry->retry = 0;
free_qry_inst(qry);
}