diff options
Diffstat (limited to 'eperd/evtdig.c')
-rw-r--r-- | eperd/evtdig.c | 976 |
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); } |