From b1b227fa5e00d08af047ab9a012211b66c6b0f13 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Fri, 15 May 2015 10:25:18 +0200 Subject: ripe-atlas-fw: imported version 4610 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- .config | 2 +- checksum | 4 +- eperd/eooqd.c | 303 +++------------ eperd/eperd.c | 6 +- eperd/evtdig.c | 976 +++++++++++++++++++++++++++++++++--------------- eperd/ping.c | 8 +- eperd/readresolv.c | 64 +++- eperd/readresolv.h | 4 +- eperd/sslgetcert.c | 13 +- eperd/traceroute.c | 211 ++++++++++- include/libbb.h | 1 + include/usage.h | 3 +- miscutils/perd.c | 12 +- networking/httppost.c | 61 ++- networking/sslgetcert.c | 13 +- networking/telnetd.c | 31 -- 16 files changed, 1090 insertions(+), 622 deletions(-) diff --git a/.config b/.config index 1e06edb..fe8c41e 100644 --- a/.config +++ b/.config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Busybox version: 1.13.3 -# Thu Oct 31 21:51:23 2013 +# Mon Mar 10 17:14:26 2014 # CONFIG_HAVE_DOT_CONFIG=y diff --git a/checksum b/checksum index 507305c..bcff836 100644 --- a/checksum +++ b/checksum @@ -1,2 +1,2 @@ -SHA256 50cbf293f78251170c3afbba74850ac3a17836f30542775ecad78f660ee6f68c ripe-atlas-fw-4560.tar.gz -SHA512 27eab255f332dc0fc88036657243de806dff938d954d7bab538f3e7a4c3c55f777c0384236a17c3a1f47b76b140e266c0335d52f8e113b2de25ef9031642c387 ripe-atlas-fw-4560.tar.gz +9220584710f5cb827a35a20b139231c774d60bc1e66706cc42c6808a34a28b34 ripe-atlas-fw-4570.tar.gz +5fa4008d6321d66ed15235dd51bef6fbee1c455dccdf01c1b9a92db979a82fdc307dd2f11cc9f79de2adf467638954180c4d5b9ad9e30501f699af7691079bbc ripe-atlas-fw-4570.tar.gz diff --git a/eperd/eooqd.c b/eperd/eooqd.c index ea7162f..7e071c0 100644 --- a/eperd/eooqd.c +++ b/eperd/eooqd.c @@ -17,6 +17,7 @@ #define SUFFIX ".curr" #define OOQD_NEW_PREFIX "/home/atlas/data/new/ooq" #define OOQD_OUT "/home/atlas/data/ooq.out/ooq" +#define ATLAS_SESSION_FILE "/home/atlas/status/con_session_id.txt" #define ATLAS_NARGS 64 /* Max arguments to a built-in command */ #define ATLAS_ARGSIZE 512 /* Max size of the command line */ @@ -34,7 +35,7 @@ struct slot static struct { char *queue_file; - char *atlas_id; + const char *atlas_id; char curr_qfile[256]; FILE *curr_file; int max_busy; @@ -58,8 +59,8 @@ static struct builtin }; static const char *atlas_id; +static const char *out_filename; -static void process(FILE *file); static void report(const char *fmt, ...); static void report_err(const char *fmt, ...); @@ -71,12 +72,15 @@ static void post_results(void); static void skip_space(char *cp, char **ncpp); static void skip_nonspace(char *cp, char **ncpp); static void find_eos(char *cp, char **ncpp); +static void check_resolv_conf2(const char *out_file, const char *atlasid); +static const char *get_session_id(void); + +extern int httppost_main(int argc, char *argv[]); /* in networking/httppost.c */ int eooqd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int eooqd_main(int argc, char *argv[]) { int r; - uint32_t opt; char *pid_file_name; struct event *checkQueueEvent, *rePostEvent; struct timeval tv; @@ -84,7 +88,8 @@ int eooqd_main(int argc, char *argv[]) atlas_id= NULL; pid_file_name= NULL; - opt = getopt32(argv, "A:P:", &atlas_id, &pid_file_name); + (void)getopt32(argv, "A:P:O:", &atlas_id, &pid_file_name, + &out_filename); if (argc != optind+1) { @@ -145,38 +150,7 @@ int eooqd_main(int argc, char *argv[]) tv.tv_sec= 60; tv.tv_usec= 0; event_add(rePostEvent, &tv); -#if 0 - for(;;) - { - /* Try to move queue_file to curr_qfile. This provide at most - * once behavior and allows producers to create a new - * queue_file while we process the old one. - */ - if (rename(queue_file, curr_qfile) == -1) - { - if (errno == ENOENT) - { - sleep(WAIT_TIME); - continue; - } - report_err("rename failed"); - return 1; - } - - file= fopen(curr_qfile, "r"); - if (file == NULL) - { - report_err("open '%s' failed", curr_qfile); - continue; - } - - process(file); - fclose(file); - - /* No need to delete curr_qfile */ - } -#endif r= event_base_loop(EventBase, 0); if (r != 0) crondlog(LVL9 "event_base_loop failed"); @@ -214,6 +188,8 @@ static void checkQueue(evutil_socket_t fd UNUSED_PARAM, { add_line(); } + + check_resolv_conf2(out_filename, atlas_id); } static void add_line(void) @@ -361,7 +337,7 @@ static void add_line(void) for (i= 0; itestops->init(argc, argv, cmddone); + cmdstate= bp->testops->init(argc, (char **)argv, cmddone); crondlog(LVL7 "init returned %p for '%s'", cmdstate, cmdline); if (cmdstate != NULL) @@ -493,7 +469,7 @@ static void check_resolv_conf2(const char *out_file, const char *atlasid) RESOLV_CONF); evdns_base_resume(DnsBase); - if (r != 0 || last_time != -1) + if ((r != 0 || last_time != -1) && out_filename != NULL) { fn= fopen(out_file, "a"); if (!fn) @@ -513,11 +489,6 @@ static void check_resolv_conf2(const char *out_file, const char *atlasid) last_time= sb.st_mtime; } -static void check_resolv_conf(void) -{ - check_resolv_conf1(); -} - static void re_post(evutil_socket_t fd UNUSED_PARAM, short what UNUSED_PARAM, void *arg UNUSED_PARAM) { @@ -529,10 +500,12 @@ static void re_post(evutil_socket_t fd UNUSED_PARAM, short what UNUSED_PARAM, static void post_results(void) { - int i, j, r, need_post; + int i, j, r, need_post, probe_id; + const char *session_id; const char *argv[20]; char from_filename[80]; char to_filename[80]; + char url[200]; struct stat sb; for (j= 0; j<5; j++) @@ -583,6 +556,16 @@ static void post_results(void) if (!need_post) break; + probe_id= get_probe_id(); + if (probe_id == -1) + break; + session_id= get_session_id(); + if (session_id == NULL) + break; + snprintf(url, sizeof(url), + "http://127.0.0.1:8080/?PROBE_ID=%d&SESSION_ID=%s&SRC=oneoff", + probe_id, session_id); + i= 0; argv[i++]= "httppost"; argv[i++]= "-A"; @@ -596,9 +579,9 @@ static void post_results(void) argv[i++]= "/home/atlas/status/con_session_id.txt"; argv[i++]= "-O"; argv[i++]= "/home/atlas/data/new/ooq_sent.vol"; - argv[i++]= "http://127.0.0.1:8080/"; + argv[i++]= url; argv[i]= NULL; - r= httppost_main(i, argv); + r= httppost_main(i, (char **)argv); if (r != 0) { report("httppost failed with %d", r); @@ -608,6 +591,34 @@ static void post_results(void) } } +static const char *get_session_id(void) +{ + static char session_id[80]; + + char *cp; + FILE *file; + + file= fopen(ATLAS_SESSION_FILE, "r"); + if (file == NULL) + { + return NULL; + } + + /* Skip first empty line */ + fgets(session_id, sizeof(session_id), file); + + if (fgets(session_id, sizeof(session_id), file) == NULL) + { + fclose(file); + return NULL; + } + fclose(file); + cp= strchr(session_id, '\n'); + if (cp) + *cp= '\0'; + return session_id; +} + static void skip_space(char *cp, char **ncpp) { while (cp[0] != '\0' && isspace(*(unsigned char *)cp)) @@ -629,208 +640,6 @@ static void find_eos(char *cp, char **ncpp) *ncpp= cp; } -#if 0 -static void process(FILE *file) -{ - int i, argc, do_append, saved_fd, out_fd, flags; - size_t len; - char *cp, *ncp, *outfile; - struct builtin *bp; - char line[256]; - char *argv[NARGS]; - -printf("in process\n"); - while (cp= fgets(line, sizeof(line), file), cp != NULL) - { -printf("got cp %p, line %p, '%s'\n", cp, line, cp); - if (strchr(line, '\n') == NULL) - { - report("line '%s' too long", line); - return; - } - - /* Skip leading white space */ - cp= line; - while (cp[0] != '\0' && isspace((unsigned char)cp[0])) - cp++; - - if (cp[0] == '\0' || cp[0] == '#') - continue; /* Empty or comment line */ - - for (bp= builtin_cmds; bp->cmd != NULL; bp++) - { - len= strlen(bp->cmd); - if (strncmp(cp, bp->cmd, len) != 0) - continue; - if (cp[len] != ' ') - continue; - break; - } - if (bp->cmd == NULL) - { - report("nothing found for '%s'", cp); - return; /* Nothing found */ - } - - /* Remove trailing white space */ - len= strlen(cp); - while (len > 0 && isspace((unsigned char)cp[len-1])) - { - cp[len-1]= '\0'; - len--; - } - - outfile= NULL; - do_append= 0; - - /* Split the command line */ - argc= 0; - argv[argc]= cp; - skip_nonspace(cp, &ncp); - cp= ncp; - - for(;;) - { - /* End of list */ - if (cp[0] == '\0') - { - argc++; - break; - } - - /* Find start of next argument */ - skip_space(cp, &ncp); - - /* Terminate current one */ - cp[0]= '\0'; - - /* Special case for '>' */ - if (argv[argc][0] == '>') - { - cp= argv[argc]+1; - if (cp[0] == '>') - { - /* Append */ - do_append= 1; - cp++; - } - if (cp[0] != '\0') - { - /* Filename immediately follows '>' */ - outfile= cp; - - /* And move on with the next option */ - } - else - { - /* Get the next argument */ - outfile= ncp; - cp= ncp; - skip_nonspace(cp, &ncp); - cp= ncp; - - if (cp[0] == '\0') - break; - - /* Find start of next argument */ - skip_space(cp, &ncp); - *cp= '\0'; - - if (ncp[0] == '\0') - break; /* No more arguments */ - } - } - else - { - argc++; - } - - if (argc >= NARGS-1) - { - report("command line '%s', too arguments", - line); - continue; /* Just skip it */ - } - - cp= ncp; - argv[argc]= cp; - if (cp[0] == '"') - { - /* Special code for strings */ - find_eos(cp+1, &ncp); - if (ncp[0] != '"') - { - report( - "command line '%s', end of string not found", - line); - continue; /* Just skip it */ - } - argv[argc]= cp+1; - cp= ncp; - cp[0]= '\0'; - cp++; - } - else - { - skip_nonspace(cp, &ncp); - cp= ncp; - } - } - - if (argc >= NARGS) - { - report("command line '%s', too many arguments", line); - return; - } - argv[argc]= NULL; - - for (i= 0; ifunc(argc, argv); - - if (outfile) - { - fflush(stdout); - dup2(saved_fd, 1); - close(saved_fd); - } - } -} -#endif - static void report(const char *fmt, ...) { va_list ap; diff --git a/eperd/eperd.c b/eperd/eperd.c index bfa3615..131f5d5 100644 --- a/eperd/eperd.c +++ b/eperd/eperd.c @@ -52,6 +52,8 @@ #define MAXLINES 256 /* max lines in non-root crontabs */ #endif +#define MAX_INTERVAL (2*366*24*3600) /* No intervals bigger than 2 years */ + #define URANDOM_DEV "/dev/urandom" #define ATLAS_FW_VERSION "/home/atlas/state/FIRMWARE_APPS_VERSION" @@ -496,7 +498,9 @@ static void SynchronizeFile(const char *fileName) line->start_time= strtoul(tokens[1], &check1, 10); line->end_time= strtoul(tokens[2], &check2, 10); - if (line->interval <= 0 || check0[0] != '\0' || + if (line->interval <= 0 || + line->interval > MAX_INTERVAL || + check0[0] != '\0' || check1[0] != '\0' || check2[0] != '\0') { 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 + * Copyright (c) 2011-2014 RIPE NCC * Copyright (c) 2009 Rocco Carbone * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ @@ -29,15 +29,17 @@ #include #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;ierr.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); } diff --git a/eperd/ping.c b/eperd/ping.c index 8a6d2a2..16aa8fe 100644 --- a/eperd/ping.c +++ b/eperd/ping.c @@ -354,7 +354,8 @@ static void ping_cb(int result, int bytes, int psize, pingstate->ttl= ttl; } namebuf1[0]= '\0'; - getnameinfo(&pingstate->loc_sin6, loc_socklen, namebuf1, + getnameinfo((struct sockaddr *)&pingstate->loc_sin6, + loc_socklen, namebuf1, sizeof(namebuf1), NULL, 0, NI_NUMERICHOST); namebuf2[0]= '\0'; getnameinfo(loc_sa, loc_socklen, namebuf2, @@ -560,8 +561,6 @@ static void ping_xmit(struct pingstate *host) int nsent, fd4, fd6, t_errno, r; - host->send_error= 0; - host->got_reply= 0; if (host->sentpkts >= host->maxpkts) { /* Done. */ @@ -1165,6 +1164,9 @@ static void ping_start2(void *state) pingstate->sentpkts= 0; pingstate->cursize= pingstate->maxsize; + pingstate->send_error= 0; + pingstate->got_reply= 0; + ping_xmit(pingstate); } diff --git a/eperd/readresolv.c b/eperd/readresolv.c index 9d3b8c9..cd43bd3 100644 --- a/eperd/readresolv.c +++ b/eperd/readresolv.c @@ -6,6 +6,8 @@ #define LINEL (INET6_ADDRSTRLEN * 2) #include "libbb.h" #include "resolv.h" +#include "eperd.h" +#include static void nameserver_ip_add (char *nsentry, char *ip_as_string) { @@ -39,18 +41,72 @@ static int resolv_conf_parse_line (char *nsentry, char *line) return 0; } -int get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2]) +void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2], + int *resolv_max) { + +#ifndef RESOLV_CONF +#define RESOLV_CONF "/etc/resolv.conf" +#endif char buf[LINEL]; + char *buf_start; int i = 0; + time_t now; + int r; + struct stat sb; + + static resolv_last_check = -1; + static time_t last_time= -1; + + now = time(NULL); + + if(*resolv_max){ + if ( pow (resolv_last_check - now, 2) > 3) { + crondlog(LVL5 "check the %s", RESOLV_CONF); + } + else { + return; + } + + } + - FILE *R = fopen ("/etc/resolv.conf", "r"); + r = stat(RESOLV_CONF, &sb); + if (r == -1) + { + crondlog(LVL8 "error accessing resolv.conf: %s", + strerror(errno)); + return; + } + + resolv_last_check = now; + + if (last_time == sb.st_mtime) + { + /* nothing changed */ + crondlog(LVL5 "re-read %s. not reading this time", RESOLV_CONF); + return; + } + else { + crondlog(LVL5 "re-read %s . it has changed", RESOLV_CONF); + } + + FILE *R = fopen (RESOLV_CONF, "r"); if (R != NULL) { while ( (fgets (buf, LINEL, R)) && (i < MAXNS)) { - if(resolv_conf_parse_line(nslist[i], buf) ) + buf_start = buf; + if(resolv_conf_parse_line(nslist[i], buf) ) { + crondlog(LVL5 "parsed file %s , line %s i=%d", RESOLV_CONF, buf_start, i); i++; + } + else + crondlog(LVL5 "ERROR failed to parse from %s i=%d, line %s", RESOLV_CONF, i, buf_start); } fclose (R); } - return i; + + last_time = sb.st_mtime; + + *resolv_max = i; + return; } diff --git a/eperd/readresolv.h b/eperd/readresolv.h index a195aaa..4c1fa83 100644 --- a/eperd/readresolv.h +++ b/eperd/readresolv.h @@ -1,5 +1,5 @@ /* * Copyright (c) 2013 RIPE NCC - * Licensed under GPLv2 or later, see file LICENSE in this tarball for detai + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -int get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2]); +void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2], int *resolv_max); diff --git a/eperd/sslgetcert.c b/eperd/sslgetcert.c index 5b18b33..2b71cc4 100644 --- a/eperd/sslgetcert.c +++ b/eperd/sslgetcert.c @@ -909,7 +909,7 @@ static int eat_server_hello(struct state *state) static int eat_certificate(struct state *state) { - int i, n, r, first, slen; + int i, n, r, first, slen, need_nl; size_t o, len; uint8_t *p; struct msgbuf *msgbuf; @@ -1019,14 +1019,23 @@ static int eat_certificate(struct state *state) buf_add_b64(&tmpbuf, p+o+3, slen); fprintf(fh, "%s\"-----BEGIN CERTIFICATE-----\\n", !first ? ", " : ""); + need_nl= 0; for (i= tmpbuf.offset; i sizeof(base->packet)) + return; + + ehlen= totsize/8 - 1; + if (ehlen > 255) + return; + + memset(base->packet, '\0', totsize); + base->packet[1]= ehlen; + for (i= 2; ipacket[i]= OPT_PAD1; + i++; + continue; + } + padlen -= 2; + if (padlen > 255) + padlen= 255; + base->packet[i]= OPT_PADN; + base->packet[i+1]= padlen; + i += 2+padlen; + } + if (hbh_dest) + { + setsockopt(sock, IPPROTO_IPV6, IPV6_DSTOPTS, base->packet, + totsize); + } + else + { + setsockopt(sock, IPPROTO_IPV6, IPV6_HOPOPTS, base->packet, + totsize); + } +} + static int in_cksum(unsigned short *buf, int sz) { int nleft = sz; @@ -461,6 +521,19 @@ static void send_pkt(struct trtstate *state) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); +#if 1 + if (state->hbhoptsize != 0) + { + do_hbh_dest_opt(base, sock, 0 /* hbh */, + state->hbhoptsize); + } + if (state->destoptsize != 0) + { + do_hbh_dest_opt(base, sock, 1 /* dest */, + state->destoptsize); + } +#endif + /* Bind to source addr/port */ r= bind(sock, (struct sockaddr *)&state->loc_sin6, @@ -567,6 +640,11 @@ static void send_pkt(struct trtstate *state) setsockopt(base->v6icmp_snd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)); + do_hbh_dest_opt(base, base->v6icmp_snd, 0 /* hbh */, + state->hbhoptsize); + do_hbh_dest_opt(base, base->v6icmp_snd, 1 /* dest */, + state->destoptsize); + icmp6_hdr= (struct icmp6_hdr *)base->packet; icmp6_hdr->icmp6_type= ICMP6_ECHO_REQUEST; icmp6_hdr->icmp6_code= 0; @@ -667,6 +745,17 @@ static void send_pkt(struct trtstate *state) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (state->hbhoptsize != 0) + { + do_hbh_dest_opt(base, sock, 0 /* hbh */, + state->hbhoptsize); + } + if (state->destoptsize != 0) + { + do_hbh_dest_opt(base, sock, 1 /* dest */, + state->destoptsize); + } + /* Bind to source addr/port */ r= bind(sock, (struct sockaddr *)&state->loc_sin6, @@ -1828,7 +1917,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family (late || isDup) ? ", " : "", inet_ntoa(remote.sin_addr)); add_str(state, line); -printf("nrecv=%d\n", nrecv); snprintf(line, sizeof(line), ", \"ttl\":%d, \"size\":%d", ip->ip_ttl, (int)nrecv-IPHDR-ICMP_MINLEN); @@ -2252,7 +2340,7 @@ printf("got seq %d, expected %d\n", seq, state->seq); inet_ntoa(remote.sin_addr)); add_str(state, line); snprintf(line, sizeof(line), ", \"ttl\":%d, \"size\":%d", - ip->ip_ttl, (int)nrecv - IPHDR - sizeof(*tcphdr)); + ip->ip_ttl, (int)(nrecv - IPHDR - sizeof(*tcphdr))); add_str(state, line); snprintf(line, sizeof(line), ", \"flags\":\"%s%s%s%s%s%s\"", (tcphdr->fin ? "F" : ""), @@ -2434,7 +2522,7 @@ printf("got seq %d, expected %d\n", seq, state->seq); inet_ntop(AF_INET6, &remote.sin6_addr, buf, sizeof(buf))); add_str(state, line); snprintf(line, sizeof(line), ", \"ttl\":%d, \"size\":%d", - rcvdttl, (int)nrecv - sizeof(*tcphdr)); + rcvdttl, (int)(nrecv - sizeof(*tcphdr))); add_str(state, line); snprintf(line, sizeof(line), ", \"flags\":\"%s%s%s%s%s%s\"", (tcphdr->fin ? "F" : ""), @@ -2485,12 +2573,13 @@ static void ready_callback6(int __attribute((unused)) unused, { ssize_t nrecv; int ind, rcvdttl, late, isDup, nxt, icmp_prefixlen, offset; - unsigned nextmtu, seq; + unsigned nextmtu, seq, optlen, hbhoptsize, dstoptsize; size_t ehdrsiz, v6info_siz, siz; struct trtbase *base; struct trtstate *state; struct ip6_hdr *eip; struct ip6_frag *frag; + struct ip6_ext *opthdr; struct icmp6_hdr *icmp, *eicmp; struct tcphdr *etcp; struct udphdr *eudp; @@ -2561,6 +2650,8 @@ static void ready_callback6(int __attribute((unused)) unused, icmp= (struct icmp6_hdr *)&base->packet; + hbhoptsize= 0; + dstoptsize= 0; if (icmp->icmp6_type == ICMP6_DST_UNREACH || icmp->icmp6_type == ICMP6_PACKET_TOO_BIG || icmp->icmp6_type == ICMP6_TIME_EXCEEDED) @@ -2579,6 +2670,8 @@ static void ready_callback6(int __attribute((unused)) unused, /* Make sure we have TCP, UDP, ICMP or a fragment header */ if (eip->ip6_nxt == IPPROTO_FRAGMENT || + eip->ip6_nxt == IPPROTO_HOPOPTS || + eip->ip6_nxt == IPPROTO_DSTOPTS || eip->ip6_nxt == IPPROTO_TCP || eip->ip6_nxt == IPPROTO_UDP || eip->ip6_nxt == IPPROTO_ICMPV6) @@ -2586,6 +2679,35 @@ static void ready_callback6(int __attribute((unused)) unused, ehdrsiz= 0; frag= NULL; nxt= eip->ip6_nxt; + ptr= &eip[1]; + if (nxt == IPPROTO_HOPOPTS) + { + /* Make sure the options header is completely + * there. + */ + if (nrecv < sizeof(*icmp) + sizeof(*eip) + + sizeof(*opthdr)) + { +#if 0 + printf( + "ready_callback6: too short %d (icmp+ip+opt)\n", + (int)nrecv); +#endif + return; + } + opthdr= (struct ip6_ext *)&eip[1]; + hbhoptsize= 8*opthdr->ip6e_len; + optlen= hbhoptsize+8; + if (nrecv < sizeof(*icmp) + sizeof(*eip) + + optlen) + { + /* Does not contain the full header */ + return; + } + ehdrsiz= optlen; + nxt= opthdr->ip6e_nxt; + ptr= ((char *)opthdr)+optlen; + } if (nxt == IPPROTO_FRAGMENT) { /* Make sure the fragment header is completely @@ -2611,6 +2733,35 @@ static void ready_callback6(int __attribute((unused)) unused, } ehdrsiz= sizeof(*frag); nxt= frag->ip6f_nxt; + ptr= &frag[1]; + } + if (nxt == IPPROTO_DSTOPTS) + { + /* Make sure the options header is completely + * there. + */ + if (nrecv < sizeof(*icmp) + sizeof(*eip) + + sizeof(*opthdr)) + { +#if 0 + printf( + "ready_callback6: too short %d (icmp+ip+opt)\n", + (int)nrecv); +#endif + return; + } + opthdr= (struct ip6_ext *)&eip[1]; + dstoptsize= 8*opthdr->ip6e_len; + optlen= dstoptsize+8; + if (nrecv < sizeof(*icmp) + sizeof(*eip) + + optlen) + { + /* Does not contain the full header */ + return; + } + ehdrsiz= optlen; + nxt= opthdr->ip6e_nxt; + ptr= ((char *)opthdr)+optlen; } v6info_siz= sizeof(*v6info); @@ -2643,7 +2794,6 @@ static void ready_callback6(int __attribute((unused)) unused, eudp= NULL; eicmp= NULL; v6info= NULL; - ptr= (frag ? (void *)&frag[1] : (void *)&eip[1]); if (nxt == IPPROTO_TCP) { etcp= (struct tcphdr *)ptr; @@ -2660,11 +2810,14 @@ static void ready_callback6(int __attribute((unused)) unused, } #if 0 - printf( + if (v6info) + { + printf( "ready_callback6: pid = htonl(%d), id = htonl(%d), seq = htonl(%d)\n", - ntohl(v6info->pid), - ntohl(v6info->id), - ntohl(v6info->seq)); + ntohl(v6info->pid), + ntohl(v6info->id), + ntohl(v6info->seq)); + } #endif if (etcp) @@ -2818,7 +2971,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family add_str(state, line); snprintf(line, sizeof(line), ", \"ttl\":%d, \"rtt\":%.3f, \"size\":%d", - rcvdttl, ms, (int)nrecv-ICMP6_HDR); + rcvdttl, ms, (int)(nrecv-ICMP6_HDR)); add_str(state, line); if (eip->ip6_hops != 1) { @@ -2826,6 +2979,18 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family eip->ip6_hops); add_str(state, line); } + if (hbhoptsize) + { + snprintf(line, sizeof(line), + ", \"hbhoptsize\":%d", hbhoptsize); + add_str(state, line); + } + if (dstoptsize) + { + snprintf(line, sizeof(line), + ", \"dstoptsize\":%d", dstoptsize); + add_str(state, line); + } #if 0 printf("ready_callback6: from %s, ttl %d", @@ -2854,6 +3019,14 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family siz += sizeof(*eicmp); else if (etcp) siz += sizeof(*etcp); + if (nextmtu < 1200) + { + /* This is IPv6, no need to go + * below 1280. Use 1200 to deal with + * off by one error or weird tunnels. + */ + nextmtu= 1200; + } if (!late && nextmtu >= siz) { nextmtu -= siz; @@ -3075,7 +3248,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family add_str(state, line); snprintf(line, sizeof(line), ", \"ttl\":%d, \"rtt\":%.3f, \"size\":%d", - rcvdttl, ms, (int)nrecv - ICMP6_HDR); + rcvdttl, ms, (int)(nrecv - ICMP6_HDR)); add_str(state, line); #if 0 @@ -3195,12 +3368,13 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[], uint32_t opt; int i, do_icmp, do_v6, dont_fragment, delay_name_res, do_tcp, do_udp; unsigned count, duptimeout, firsthop, gaplimit, maxhops, maxpacksize, - parismod, timeout; /* must be int-sized */ + hbhoptsize, destoptsize, parismod, timeout; + /* must be int-sized */ size_t newsiz; char *str_Atlas; const char *hostname; char *out_filename; - char *destportstr; + const char *destportstr; char *check; struct trtstate *state; sa_family_t af; @@ -3226,14 +3400,15 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[], parismod= 16; str_Atlas= NULL; out_filename= NULL; - opt_complementary = "=1:4--6:i--u:a+:c+:f+:g+:m+:w+:z+:S+"; + opt_complementary = "=1:4--6:i--u:a+:c+:f+:g+:m+:w+:z+:S+:H+:D+"; for (i= 0; argv[i] != NULL; i++) printf("argv[%d] = '%s'\n", i, argv[i]); opt = getopt32(argv, TRACEROUTE_OPT_STRING, &parismod, &count, &firsthop, &gaplimit, &maxhops, &destportstr, &timeout, - &duptimeout, &str_Atlas, &out_filename, &maxpacksize); + &duptimeout, &str_Atlas, &out_filename, &maxpacksize, + &hbhoptsize, &destoptsize); hostname = argv[optind]; if (opt == 0xffffffff) @@ -3319,6 +3494,8 @@ for (i= 0; argv[i] != NULL; i++) state->do_v6= do_v6; state->dont_fragment= dont_fragment; state->delay_name_res= delay_name_res; + state->hbhoptsize= hbhoptsize; + state->destoptsize= destoptsize; state->out_filename= out_filename ? strdup(out_filename) : NULL; state->base= trt_base; state->busy= 0; diff --git a/include/libbb.h b/include/libbb.h index 229634d..d5c3178 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -313,6 +313,7 @@ extern char *bb_get_last_path_component_nostrip(const char *path) FAST_FUNC; extern int validate_filename(const char *path, const char *prefix); extern int validate_atlas_id(const char *atlas_id); +extern int get_probe_id(void); int ndelay_on(int fd) FAST_FUNC; int ndelay_off(int fd) FAST_FUNC; diff --git a/include/usage.h b/include/usage.h index e83abbd..ea3b78b 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1062,7 +1062,7 @@ #define evtraceroute_trivial_usage \ "-[46FIrTU] [-a ] [-c ] [-f ]" \ -"\n [-g ] [-m ] [-w ] [-z ] [-A ] [-O ]" \ +"\n [-g ] [-m ] [-p ] [-w ] [-z ] [-A ] [-O ]" \ "\n [-S ]" #define evtraceroute_full_usage "\n" \ @@ -1078,6 +1078,7 @@ "\n -f Starting hop" \ "\n -g Gap limit" \ "\n -m Max hops" \ + "\n -p Destination port" \ "\n -w No reply timeout (ms)" \ "\n -z Dup timeout (ms)" \ "\n -A Atlas measurement ID" \ diff --git a/miscutils/perd.c b/miscutils/perd.c index 1058dea..3a7b496 100644 --- a/miscutils/perd.c +++ b/miscutils/perd.c @@ -43,6 +43,8 @@ #define MAXLINES 256 /* max lines in non-root crontabs */ #endif +#define MAX_INTERVAL (2*366*24*3600) /* No intervals bigger than 2 years */ + #ifdef ATLAS #include @@ -674,10 +676,9 @@ static void SynchronizeFile(const char *fileName) line->start_time= strtoul(tokens[1], &check1, 10); line->end_time= strtoul(tokens[2], &check2, 10); - line->nextcycle= (now-line->start_time)/ - line->interval + 1; - - if (check0[0] != '\0' || + if (line->interval <= 0 || + line->interval > MAX_INTERVAL || + check0[0] != '\0' || check1[0] != '\0' || check2[0] != '\0') { @@ -686,6 +687,9 @@ static void SynchronizeFile(const char *fileName) continue; } + line->nextcycle= (now-line->start_time)/ + line->interval + 1; + if (strcmp(tokens[3], "NONE") == 0) { line->distribution= DISTR_NONE; diff --git a/networking/httppost.c b/networking/httppost.c index 6b8b533..24f1430 100644 --- a/networking/httppost.c +++ b/networking/httppost.c @@ -50,6 +50,7 @@ char *do_dir(char *dir_name, off_t curr_size, off_t max_size, off_t *lenp); static int copy_chunked(FILE *in_file, FILE *out_file, int *found_okp); static int copy_bytes(FILE *in_file, FILE *out_file, size_t len, int *found_okp); +static int copy_all(FILE *in_file, FILE *out_file, int *found_okp); static void fatal(const char *fmt, ...); // static void fatal_err(const char *fmt, ...); static void report(const char *fmt, ...); @@ -398,6 +399,7 @@ int httppost_main(int argc, char *argv[]) goto err; fprintf(stderr, "httppost: getting reply headers \n"); server_time= 0; + content_length= -1; if (!eat_headers(tcp_file, &chunked, &content_length, &server_time)) goto err; @@ -464,16 +466,24 @@ int httppost_main(int argc, char *argv[]) else out_file= stdout; + fprintf(stderr, "httppost: chunked %d, content_length %d\n", + chunked, content_length); + found_ok= 0; if (chunked) { if (!copy_chunked(tcp_file, out_file, &found_ok)) goto err; } - else if (content_length) + else if (content_length >= 0) { if (!copy_bytes(tcp_file, out_file, content_length, &found_ok)) goto err; } + else + { + if (!copy_all(tcp_file, out_file, &found_ok)) + goto err; + } if (!found_ok) fprintf(stderr, "httppost: reply text was not equal to OK\n"); if ( opt_delete_file == 1 && found_ok) @@ -764,7 +774,6 @@ static int eat_headers(FILE *tcp_file, int *chunked, int *content_length, time_t char buffer[1024]; *chunked= 0; - *content_length= 0; while (fgets(buffer, sizeof(buffer), tcp_file) != NULL) { line= buffer; @@ -1086,6 +1095,8 @@ static int copy_chunked(FILE *in_file, FILE *out_file, int *found_okp) } offset += size; + fprintf(stderr, "httppost: chunk data '%.*s'\n", + (int)size, buffer); for (i= 0; i