From 7f8d8aa7a9e542524e9edfcca1fe1220abbf8e40 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Wed, 20 Jan 2016 18:46:57 +0100 Subject: ripe-atlas-fw: imported version 4720 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- eperd/eooqd.c | 32 ++++- eperd/eperd.c | 56 +++++++++ eperd/eperd.h | 4 + eperd/evtdig.c | 142 ++++++++++++++++------- eperd/httpget.c | 55 +++++---- eperd/ntp.c | 62 ++++++++-- eperd/ping.c | 90 +++++++++++---- eperd/sslgetcert.c | 334 ++++++++++++++++++++++++++++++++++++----------------- eperd/tcputil.c | 16 +++ eperd/tcputil.h | 2 +- eperd/traceroute.c | 153 +++++++++++++++++++----- 11 files changed, 709 insertions(+), 237 deletions(-) (limited to 'eperd') diff --git a/eperd/eooqd.c b/eperd/eooqd.c index 04bfcd6..ed8ea64 100644 --- a/eperd/eooqd.c +++ b/eperd/eooqd.c @@ -189,20 +189,44 @@ static void checkQueue(evutil_socket_t fd UNUSED_PARAM, short what UNUSED_PARAM, void *arg UNUSED_PARAM) { int r; + struct stat sb; char filename[80]; if (!state->curr_file) { + if (stat(state->queue_file, &sb) == -1) + { + if (errno == ENOENT) + { + return; + } + report_err("stat failed"); + return; + } + + /* Remove curr_qfile. Renaming queue_file to curr_qfile + * will silently fail to delete queue_file if queue_file and + * curr_qfile are hard links. + */ + if (unlink(state->curr_qfile) == -1) + { + /* Expect ENOENT */ + if (errno != ENOENT) + { + report_err("unlink failed"); + return; + } + } + /* Try to move queue_file to curr_qfile. This provides at most * once behavior and allows producers to create a new * queue_file while we process the old one. */ if (rename(state->queue_file, state->curr_qfile) == -1) { - if (errno == ENOENT) - { - return; - } + /* We verified queue_file is there so any failure is + * fatal. + */ report_err("rename failed"); return; } diff --git a/eperd/eperd.c b/eperd/eperd.c index 30a485d..464cd6c 100644 --- a/eperd/eperd.c +++ b/eperd/eperd.c @@ -84,6 +84,10 @@ struct CronLine { /* For debugging */ time_t lasttime; + time_t nexttime; + time_t waittime; + time_t debug_cycle; + time_t debug_generated; }; @@ -712,6 +716,11 @@ static void set_timeout(CronLine *line, int init_next_cycle) line->start_time, line->distr_offset.tv_sec + line->distr_offset.tv_usec/1e6, now.tv_sec, tv.tv_sec); + line->debug_cycle= line->nextcycle; + line->debug_generated= now.tv_sec; + line->nexttime= line->nextcycle*line->interval + line->start_time + + line->distr_offset.tv_sec; + line->waittime= tv.tv_sec; event_add(&line->event, &tv); } @@ -1182,8 +1191,11 @@ static void EndJob(const char *user, CronLine *line) static void RunJob(evutil_socket_t __attribute__ ((unused)) fd, short __attribute__ ((unused)) what, void *arg) { + char c; + char *p; CronLine *line; struct timeval now; + FILE *fn; line= arg; @@ -1199,6 +1211,50 @@ static void RunJob(evutil_socket_t __attribute__ ((unused)) fd, crondlog(LVL7 "RubJob, now %d, end_time %d\n", now.tv_sec, line->end_time); + if (now.tv_sec < line->nexttime-10 || now.tv_sec > line->nexttime+10) + { + if (out_filename) + { + fn= fopen(out_filename, "a"); + if (!fn) + { + crondlog(DIE9 "unable to append to '%s'", + out_filename); + } + fprintf(fn, "RESULT { "); + if (atlas_id) + fprintf(fn, DBQ(id) ":" DBQ(%s) ", ", atlas_id); + fprintf(fn, DBQ(fw) ":" DBQ(%d) ", " DBQ(time) ":%ld, ", + get_atlas_fw_version(), (long)time(NULL)); + fprintf(fn, DBQ(reason) ": " + DBQ(inconsistent time; now %d; nexttime %d; waittime %d; cycle %d; generated %d) ", ", + (int)now.tv_sec, (int)line->nexttime, + (int)line->waittime, (int)line->debug_cycle, + (int)line->debug_generated); + + fprintf(fn, DBQ(cmd) ": \""); + for (p= line->cl_Shell; *p; p++) + { + c= *p; + if (c == '"' || c == '\\') + fprintf(fn, "\\%c", c); + else if (isprint((unsigned char)c)) + fputc(c, fn); + else + fprintf(fn, "\\u%04x", (unsigned char)c); + } + fprintf(fn, "\""); + fprintf(fn, " }\n"); + fclose(fn); + } + crondlog( + LVL7 "RunJob: weird, now %d, nexttime %d, waittime %d\n", + now.tv_sec, line->nexttime, line->waittime); + + /* Recompute nextcycle */ + set_timeout(line, 1 /*init_next_cycle*/); + return; + } if (now.tv_sec > line->end_time) { diff --git a/eperd/eperd.h b/eperd/eperd.h index e19c1a0..73b5cc6 100644 --- a/eperd/eperd.h +++ b/eperd/eperd.h @@ -56,3 +56,7 @@ extern struct testops traceroute_ops; void crondlog(const char *ctl, ...); int get_atlas_fw_version(void); + +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW 4 +#endif diff --git a/eperd/evtdig.c b/eperd/evtdig.c index 0de3541..299a79e 100644 --- a/eperd/evtdig.c +++ b/eperd/evtdig.c @@ -316,7 +316,8 @@ struct query_state { 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; + time_t xmit_time; + struct timespec xmit_time_ts; double triptime; //tdig_callback_type user_callback; @@ -462,8 +463,8 @@ static struct option longopts[]= { "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' }, + { "type", required_argument, NULL, O_TYPE }, + { "class", required_argument, NULL, O_CLASS }, { "query", required_argument, NULL, O_QUERY}, // clas CHAOS @@ -476,7 +477,7 @@ static struct option longopts[]= { "edns0", required_argument, NULL, 'e' }, { "nsid", no_argument, NULL, 'n' }, { "do", no_argument, NULL, 'd' }, - { "cd", no_argument, NULL, 'O_CD'}, + { "cd", no_argument, NULL, O_CD}, { "retry", required_argument, NULL, O_RETRY }, { "resolv", no_argument, NULL, O_RESOLV_CONF }, @@ -501,7 +502,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result); void printErrorQuick (struct query_state *qry); static void local_exit(void *state); static void *tdig_init(int argc, char *argv[], void (*done)(void *state)); -static void process_reply(void * arg, int nrecv, struct timeval now); +static void process_reply(void * arg, int nrecv, struct timespec now); static void mk_dns_buff(struct query_state *qry, u_char *packet); int ip_addr_cmp (u_int16_t af_a, void *a, u_int16_t af_b, void *b); static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, void *arg); @@ -556,26 +557,39 @@ int evtdig_main(int argc, char **argv) void print_txt_json(unsigned char *rdata, int txt_len,struct query_state *qry) { - int i; + int i, len; - AS("\"RDATA\" : \""); + AS("\"RDATA\" : [ \""); + len= -1; for(i = 0; i < txt_len; i++) { + if (len == 0) + { + AS("\", \""); + len= -1; + } + if (len == -1) + { + len= *rdata; + rdata++; + continue; + } if( (*rdata == 34 ) || (*rdata == 92 )) { - snprintf(line, DEFAULT_LINE_LENGTH, "\\%c", *(char *)rdata ); + snprintf(line, DEFAULT_LINE_LENGTH, "\\\\%03d", *(char *)rdata ); buf_add(&qry->result, line, strlen (line)); } - // Space - DEL - else if ((*rdata > 31 ) && (*rdata < 128)) { + // Space - ~ + else if ((*rdata >= ' ' ) && (*rdata <= '~')) { snprintf(line, DEFAULT_LINE_LENGTH, "%c", *(char *)rdata ); buf_add(&qry->result, line, strlen (line)); } else { - snprintf(line, DEFAULT_LINE_LENGTH, "\\u00%02X", *rdata ); + snprintf(line, DEFAULT_LINE_LENGTH, "\\\\%03d", *rdata ); buf_add(&qry->result, line, strlen (line)); } + len--; rdata++; } - AS("\""); + AS("\" ] "); } static void local_exit(void *state UNUSED_PARAM) @@ -709,7 +723,10 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet) lookup_prepend = xzalloc(DEFAULT_LINE_LENGTH + sizeof(qry->lookupname)); - snprintf(lookup_prepend, (sizeof(qry->lookupname) + DEFAULT_LINE_LENGTH - 1), "%d.%lu.%s", probe_id, qry->xmit_time.tv_sec, qry->lookupname); + snprintf(lookup_prepend, (sizeof(qry->lookupname) + + DEFAULT_LINE_LENGTH - 1), + "%d.%lu.%s", probe_id, qry->xmit_time, + qry->lookupname); ChangetoDnsNameFormat(qname, lookup_prepend); // fill the query portion. @@ -783,12 +800,12 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet) /* Attempt to transmit a UDP DNS Request to a serveri. TCP is else where */ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h) { - int fd; + int r, fd; sa_family_t af; struct query_state *qry = h; struct tdig_base *base = qry->base; uint32_t nsent = 0; - u_char *outbuff; + u_char *outbuff= NULL; int err = 0; /* Clean the no reply timer (if any was previously set) */ @@ -798,7 +815,8 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event outbuff = xzalloc(MAX_DNS_OUT_BUF_SIZE); bzero(outbuff, MAX_DNS_OUT_BUF_SIZE); //AA delete qry->outbuff = outbuff; - gettimeofday(&qry->xmit_time, NULL); + qry->xmit_time= time(NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &qry->xmit_time_ts); mk_dns_buff(qry, outbuff); do { if (qry->udp_fd != -1) @@ -815,6 +833,8 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event snprintf(line, DEFAULT_LINE_LENGTH, "%s \"socket\" : \"socket failed %s\"", qry->err.size ? ", " : "", strerror(errno)); buf_add(&qry->err, line, strlen(line)); printReply (qry, 0, NULL); + free (outbuff); + outbuff = NULL; return; } @@ -835,10 +855,28 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event qry->err.size ? ", " : ""); buf_add(&qry->err, line, strlen(line)); printReply (qry, 0, NULL); + free (outbuff); + outbuff = NULL; return; } } + if (!qry->opt_resolv_conf) + { + r= atlas_check_addr(qry->res->ai_addr, + qry->res->ai_addrlen); + if (r == -1) + { + free (outbuff); + outbuff = NULL; + snprintf(line, DEFAULT_LINE_LENGTH, + "%s \"reason\" : \"address not allowed\"", + qry->err.size ? ", " : ""); + buf_add(&qry->err, line, strlen(line)); + printReply (qry, 0, NULL); + return; + } + } qry->loc_socklen = sizeof(qry->loc_sin6); if (connect(qry->udp_fd, qry->res->ai_addr, qry->res->ai_addrlen) == -1) { @@ -848,6 +886,8 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event strerror(errno)); buf_add(&qry->err, line, strlen(line)); printReply (qry, 0, NULL); + free (outbuff); + outbuff = NULL; return; } @@ -973,6 +1013,11 @@ static void tcp_reporterr(struct tu_env *env, enum tu_err cause, buf_add(&qry->err, line, strlen(line)); break; + case TU_BAD_ADDR: + snprintf(line, DEFAULT_LINE_LENGTH, "%s \"TU_BAD_ADDR\" : true", qry->err.size ? ", " : ""); + buf_add(&qry->err, line, strlen(line)); + break; + default: snprintf(line, DEFAULT_LINE_LENGTH, "%s \"TU_UNKNOWN\" : \"%d %s\"", qry->err.size ? ", " : "", cause, str ); crondlog(DIE9 "reporterr: bad cause %d", cause); @@ -1001,9 +1046,10 @@ static void tcp_beforeconnect(struct tu_env *env, { struct query_state * qry; qry = ENV2QRY(env); - gettimeofday(&qry->xmit_time, NULL); + qry->xmit_time= time(NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &qry->xmit_time_ts); qry->dst_ai_family = addr->sa_family; - BLURT(LVL5 "time : %d", qry->xmit_time.tv_sec); + BLURT(LVL5 "time : %d", qry->xmit_time); getnameinfo(addr, addrlen, qry->dst_addr_str, INET6_ADDRSTRLEN , NULL, 0, NI_NUMERICHOST); } @@ -1045,7 +1091,7 @@ static void tcp_readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) struct query_state *qry = ptr; int n; u_char b2[2]; - struct timeval rectime; + struct timespec rectime; struct evbuffer *input ; struct DNS_HEADER *dnsR = NULL; @@ -1062,7 +1108,7 @@ static void tcp_readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) return; } - gettimeofday(&rectime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &rectime); bzero(qry->base->packet, MAX_DNS_BUF_SIZE); input = bufferevent_get_input(bev); @@ -1086,7 +1132,10 @@ static void tcp_readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) crondlog(LVL5 "DBG: base pointer address readcb %p", qry->base ); dnsR = (struct DNS_HEADER*) qry->packet.buf; if ( ntohs(dnsR->id) == qry->qryid ) { - qry->triptime = (rectime.tv_sec - qry->xmit_time.tv_sec)*1000 + (rectime.tv_usec-qry->xmit_time.tv_usec)/1e3; + qry->triptime = (rectime.tv_sec - + qry->xmit_time_ts.tv_sec)*1000 + + (rectime.tv_nsec - + qry->xmit_time_ts.tv_nsec)/1e6; printReply (qry, qry->packet.size, (unsigned char *)qry->packet.buf); } else { @@ -1121,7 +1170,7 @@ static void tcp_writecb(struct bufferevent *bev UNUSED_PARAM, void *ptr UNUSED_P * o the one we are looking for (matching the same identifier of all the packets the program is able to send) */ -static void process_reply(void * arg, int nrecv, struct timeval now) +static void process_reply(void * arg, int nrecv, struct timespec now) { struct DNS_HEADER *dnsR = NULL; struct tdig_base * base; @@ -1149,8 +1198,9 @@ static void process_reply(void * arg, int nrecv, struct timeval now) } qry->base->recvbytes += nrecv; - gettimeofday(&now, NULL); // lave this till fix now from ready_callback6 corruption; ghoost - qry->triptime = (now.tv_sec-qry->xmit_time.tv_sec)*1000 + (now.tv_usec-qry->xmit_time.tv_usec)/1e3; + clock_gettime(CLOCK_MONOTONIC_RAW, &now); // lave this till fix now from ready_callback6 corruption; ghoost + qry->triptime = (now.tv_sec-qry->xmit_time_ts.tv_sec)*1000 + + (now.tv_nsec-qry->xmit_time_ts.tv_nsec)/1e6; /* Clean the noreply timer */ evtimer_del(&qry->noreply_timer); @@ -1162,7 +1212,7 @@ static void ready_callback (int unused UNUSED_PARAM, const short event UNUSED_PA { struct query_state * qry; int nrecv; - struct timeval rectime; + struct timespec rectime; // printf("in ready_callback\n"); @@ -1171,7 +1221,7 @@ static void ready_callback (int unused UNUSED_PARAM, const short event UNUSED_PA bzero(qry->base->packet, MAX_DNS_BUF_SIZE); /* Time the packet has been received */ - gettimeofday(&rectime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &rectime); /* Receive data from the network */ nrecv = recv(qry->udp_fd, qry->base->packet, sizeof(qry->base->packet), MSG_DONTWAIT); @@ -1189,7 +1239,7 @@ static void ready_callback6 (int unused UNUSED_PARAM, const short event UNUSED_P { struct query_state * qry; int nrecv; - struct timeval rectime; + struct timespec rectime; struct msghdr msg; struct iovec iov[1]; //char buf[INET6_ADDRSTRLEN]; @@ -1429,7 +1479,7 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state)) qry->opt_abuf = 0; break; - case 'O_TYPE': + case O_TYPE: qry->qtype = strtoul(optarg, &check, 10); if ((qry->qtype >= 0 ) && (qry->qclass < 65536)) { @@ -1448,11 +1498,11 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state)) } break; - case 'O_CD': + case O_CD: qry->opt_cd = 1; break; - case 'O_CLASS': + case O_CLASS: qry->qclass = strtoul(optarg, &check, 10); if ((qry->qclass >= 0 ) && (qry->qclass < 65536)) { @@ -1803,6 +1853,8 @@ void tdig_start (void *arg) switch(qry->qst) { case STATUS_FREE : + /* Get time in case we don't send any packet */ + qry->xmit_time= time(NULL); 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) { @@ -1820,6 +1872,7 @@ void tdig_start (void *arg) snprintf(line, DEFAULT_LINE_LENGTH, "\"nameserver\": \"no local resolvers found\""); buf_add(&qry->err, line, strlen(line)); printReply (qry, 0, NULL); + return; } } break; @@ -1838,7 +1891,8 @@ void tdig_start (void *arg) hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = 0; - gettimeofday(&qry->xmit_time, NULL); + qry->xmit_time= time(NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &qry->xmit_time_ts); qry->qst = STATUS_DNS_RESOLV; if(qry->opt_v6_only == 1) @@ -1915,6 +1969,7 @@ int tdig_base_count_queries(struct tdig_base *base) static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_PARAM, void *h) { struct timeval now; + struct timeval interval; FILE *fh; struct tdig_base *base; struct query_state *qry_h; @@ -1932,9 +1987,9 @@ static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_ if(qry_h->base->done) { - now.tv_sec = DEFAULT_STATS_REPORT_INTERVEL; - now.tv_usec = 0; - event_add(&tdig_base->statsReportEvent, &now); + interval.tv_sec = DEFAULT_STATS_REPORT_INTERVEL; + interval.tv_usec = 0; + event_add(&tdig_base->statsReportEvent, &interval); return; } @@ -1954,7 +2009,7 @@ static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_ JS(id, "9201" ); fw = get_atlas_fw_version(); JU(fw, fw); - gettimeofday(&now, NULL); + gettimeofday(&now, NULL); JS1(time, %ld, now.tv_sec); JU(sok , base->sentok); JU(rok , base->recvok); @@ -1975,10 +2030,9 @@ static void tdig_stats(int unusg_statsed UNUSED_PARAM, const short event UNUSED_ buf_cleanup(&qry->result); free(qry); - // reuse timeval now - now.tv_sec = DEFAULT_STATS_REPORT_INTERVEL; - now.tv_usec = 0; - event_add(&tdig_base->statsReportEvent, &now); + interval.tv_sec = DEFAULT_STATS_REPORT_INTERVEL; + interval.tv_usec = 0; + event_add(&tdig_base->statsReportEvent, &interval); } @@ -2171,7 +2225,7 @@ void printErrorQuick (struct query_state *qry) { fprintf(fh, ",{"); fprintf(fh, "\"id\" : \"%s\"", qry->str_Atlas); - fprintf(fh, ",\"start time\" : %ld", qry->xmit_time.tv_sec); + fprintf(fh, ",\"start time\" : %ld", qry->xmit_time); if(qry->retry) { fprintf(fh, ",\"retry\": %d", qry->retry); @@ -2218,7 +2272,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result) JD(fw, fw); if (qry->opt_rset){ - JS1(time, %ld, qry->xmit_time.tv_sec); + JS1(time, %ld, qry->xmit_time); JD(lts,lts); AS("\"resultset\" : [ {"); } @@ -2228,7 +2282,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result) AS (",{"); } - JS1(time, %ld, qry->xmit_time.tv_sec); + JS1(time, %ld, qry->xmit_time); JD(lts,lts); if ( qry->opt_resolv_conf ) { @@ -2339,7 +2393,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result) if(ntohs(answers[i].resource->type)==T_TXT) //txt { - data_len = ntohs(answers[i].resource->data_len) - 1; + data_len = ntohs(answers[i].resource->data_len); if(flagAnswer == 0) { AS(",\"answers\" : [ {"); flagAnswer++; @@ -2350,7 +2404,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result) flagAnswer++; JS (TYPE, "TXT"); JS (NAME, answers[i].name); - print_txt_json(&result[reader-result+1], data_len, qry); + print_txt_json(&result[reader-result], data_len, qry); reader = reader + ntohs(answers[i].resource->data_len); AS("}"); diff --git a/eperd/httpget.c b/eperd/httpget.c index f68ec81..92ce453 100644 --- a/eperd/httpget.c +++ b/eperd/httpget.c @@ -117,7 +117,7 @@ struct hgstate int subid; int submax; time_t gstart; - struct timeval start; + struct timespec start; double resptime; double ttr; /* Time to resolve */ double ttc; /* Time to connect */ @@ -353,9 +353,11 @@ static void timeout_callback(int __attribute((unused)) unused, #if 1 snprintf(errline, sizeof(errline), DBQ(err) ":" - DBQ(timeout reading chunk: state %d linelen %d lineoffset %d) + DBQ(timeout reading chunk: state %ld linelen %ld lineoffset %ld) ", ", - state->readstate, state->linelen, state->lineoffset); + (long)state->readstate, + (long)state->linelen, + (long)state->lineoffset); add_str(state, errline); #else add_str(state, DBQ(err) ":" DBQ(timeout reading chunk) ", "); @@ -866,7 +868,7 @@ static int get_input(struct hgstate *state) { int n; double t; - struct timeval endtime; + struct timespec endtime; char line[80]; /* Assume that we always end up with a full buffer anyway */ @@ -900,9 +902,9 @@ static int get_input(struct hgstate *state) if (state->etim >= 2 && state->report_roffset) { - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); t= (endtime.tv_sec-state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; + (endtime.tv_nsec-state->start.tv_nsec)/1e6; if (state->roffset != 0) add_str2(state, ","); snprintf(line, sizeof(line), @@ -1025,7 +1027,7 @@ static void readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) char *cp, *ncp, *check, *line; const char *prefix, *kw; struct hgstate *state; - struct timeval endtime; + struct timespec endtime; state= ENV2STATE(ptr); @@ -1053,10 +1055,10 @@ static void readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) switch(state->readstate) { case READ_FIRST: - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); state->ttfb= (endtime.tv_sec- state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; + (endtime.tv_nsec-state->start.tv_nsec)/1e6; state->readstate= READ_STATUS; state->roffset= 0; if (state->etim >= 2) @@ -1557,12 +1559,12 @@ static void readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) if (state->bev) { state->bev= NULL; - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); state->resptime= (endtime.tv_sec- state->start.tv_sec)*1e3 + - (endtime.tv_usec- - state->start.tv_usec)/1e3; + (endtime.tv_nsec- + state->start.tv_nsec)/1e6; report(state); } return; @@ -1619,7 +1621,7 @@ static void writecb(struct bufferevent *bev, void *ptr) struct evbuffer *output; off_t cLength; struct stat sb; - struct timeval endtime; + struct timespec endtime; state= ENV2STATE(ptr); @@ -1628,10 +1630,10 @@ static void writecb(struct bufferevent *bev, void *ptr) switch(state->writestate) { case WRITE_FIRST: - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); state->ttc= (endtime.tv_sec- state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; + (endtime.tv_nsec-state->start.tv_nsec)/1e6; state->writestate= WRITE_HEADER; continue; case WRITE_HEADER: @@ -1733,7 +1735,7 @@ static void writecb(struct bufferevent *bev, void *ptr) static void err_reading(struct hgstate *state) { - struct timeval endtime; + struct timespec endtime; switch(state->readstate) { @@ -1762,9 +1764,9 @@ static void err_reading(struct hgstate *state) add_str(state, DBQ(err) ":" DBQ(error reading body) ", "); } - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); state->resptime= (endtime.tv_sec-state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; + (endtime.tv_nsec-state->start.tv_nsec)/1e6; report(state); break; default: @@ -1785,7 +1787,7 @@ static void beforeconnect(struct tu_env *env, struct sockaddr *addr, socklen_t addrlen) { struct hgstate *state; - struct timeval endtime; + struct timespec endtime; state= ENV2STATE(env); @@ -1811,12 +1813,12 @@ static void beforeconnect(struct tu_env *env, if (state->first_connect) { - gettimeofday(&endtime, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); state->ttr= (endtime.tv_sec-state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; + (endtime.tv_nsec-state->start.tv_nsec)/1e6; state->first_connect= 0; } - gettimeofday(&state->start, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &state->start); } @@ -1866,6 +1868,13 @@ static void reporterr(struct tu_env *env, enum tu_err cause, report(state); break; + case TU_BAD_ADDR: + add_str(state, "{ " DBQ(error) ": " + DBQ(address not allowed) " }"); + state->dnserr= 1; + report(state); + break; + default: crondlog(DIE9 "reporterr: bad cause %d", cause); } @@ -1907,7 +1916,7 @@ static void httpget_start(void *state) hgstate->readstate= READ_STATUS; hgstate->writestate= WRITE_HEADER; hgstate->gstart= time(NULL); - gettimeofday(&hgstate->start, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &hgstate->start); hgstate->first_connect= 1; memset(&hints, '\0', sizeof(hints)); diff --git a/eperd/ntp.c b/eperd/ntp.c index 457f34a..7dc1109 100644 --- a/eperd/ntp.c +++ b/eperd/ntp.c @@ -5,6 +5,7 @@ */ #include "libbb.h" +#include #include #include #include @@ -260,14 +261,13 @@ static void format_stratum(char *line, size_t size, uint8_t stratum) static void format_8bit(char *line, size_t size, const char *label, int8_t value) { - if (value >= 0) + if (value >= 0 && value < 32) { - snprintf(line, size, DBQ(%s) ": %d", label, 1 << value); + snprintf(line, size, DBQ(%s) ": %u", label, 1U << value); } else { - snprintf(line, size, DBQ(%s) ": %g", label, - 1.0 / (1 << -value)); + snprintf(line, size, DBQ(%s) ": %g", label, pow(2, value)); } } @@ -280,10 +280,33 @@ static void format_short_ts(char *line, size_t size, const char *label, static void format_ref_id(char *line, size_t size, uint32_t value, uint8_t stratum) { + int i; + size_t offset; + unsigned char *p; + char line2[40]; + if (stratum == 0 || stratum == 1) { - snprintf(line, size, DBQ(ref-id) ": " DBQ(%.4s), - (char *)&value); + line2[0]= '\0'; + for (i= 0, p= (unsigned char *)&value; + i= 127) + { + snprintf(line2+offset, sizeof(line2)-offset, + "\\\\x%02x", *p); + } + else + { + snprintf(line2+offset, sizeof(line2)-offset, + "%c", *p); + } + + } + snprintf(line, size, DBQ(ref-id) ": " DBQ(%s), + line2); } else { @@ -360,7 +383,7 @@ static void report(struct ntpstate *state) state->dnsip ? (state->do_v6 ? 6 : 4) : (state->sin6.sin6_family == AF_INET6 ? 6 : 4)); - if (!state->first) + if (!state->first && !state->dnsip) { format_li(line, sizeof(line), state->ntp_flags); fprintf(fh, ", %s", line); @@ -1763,6 +1786,9 @@ static int create_socket(struct ntpstate *state) protocol= 0; state->socket= xsocket(af, type, protocol); +#if 0 + { errno= ENOSYS; state->socket= -1; } +#endif if (state->socket == -1) { serrno= errno; @@ -1799,7 +1825,7 @@ static int create_socket(struct ntpstate *state) serrno= errno; snprintf(line, sizeof(line), - ", " DBQ(error) ":" DBQ(connect failed: %s) " }", + "{ " DBQ(error) ":" DBQ(connect failed: %s) " }", strerror(serrno)); add_str(state, line); report(state); @@ -1832,7 +1858,7 @@ static int create_socket(struct ntpstate *state) static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) { - int count; + int r, count; struct ntpstate *env; struct evutil_addrinfo *cur; char line[160]; @@ -1884,6 +1910,24 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) memcpy(&env->sin6, env->dns_curr->ai_addr, env->socklen); + r= atlas_check_addr((struct sockaddr *)&env->sin6, + env->socklen); + if (r == -1) + { + if (env->result) free(env->result); + env->resmax= 80; + env->result= xmalloc(env->resmax); + env->reslen= 0; + + env->starttime= time(NULL); + snprintf(line, sizeof(line), + "{ " DBQ(error) ":" DBQ(address not allowed) " }"); + add_str(env, line); + env->dnsip= 1; + report(env); + return; + } + traceroute_start2(env); evutil_freeaddrinfo(env->dns_res); diff --git a/eperd/ping.c b/eperd/ping.c index 53cbbe5..0b8d1b2 100644 --- a/eperd/ping.c +++ b/eperd/ping.c @@ -58,6 +58,7 @@ enum #define PING_ERR_SENDTO 4 /* Sendto system call failed */ #define PING_ERR_DNS 5 /* DNS error */ #define PING_ERR_DNS_NO_ADDR 6 /* DNS no suitable addresses */ +#define PING_ERR_BAD_ADDR 7 /* Addresses is not allowed */ #define PING_ERR_SHUTDOWN 10 /* The request was canceled because the PING subsystem was shut down */ #define PING_ERR_CANCEL 12 /* The request was canceled via a call to evping_cancel_request */ #define PING_ERR_UNKNOWN 16 /* An unknown error occurred */ @@ -158,7 +159,7 @@ struct pingstate * and it is used to relate each response with the corresponding request */ struct evdata { - struct timeval ts; + struct timespec ts; uint32_t index; struct cookie cookie; }; @@ -271,10 +272,10 @@ static void ping_cb(int result, int bytes, int psize, struct sockaddr *sa, socklen_t socklen, struct sockaddr *loc_sa, socklen_t loc_socklen, int seq, int ttl, - struct timeval * elapsed, void * arg) + struct timespec * elapsed, void * arg) { struct pingstate *pingstate; - unsigned long usecs; + double nsecs; char namebuf1[NI_MAXHOST], namebuf2[NI_MAXHOST]; char line[256]; @@ -304,7 +305,7 @@ static void ping_cb(int result, int bytes, int psize, if (result == PING_ERR_NONE || result == PING_ERR_DUP) { /* Got a ping reply */ - usecs= (elapsed->tv_sec * 1000000 + elapsed->tv_usec); + nsecs= (elapsed->tv_sec * 1e9 + elapsed->tv_nsec); snprintf(line, sizeof(line), "%s{ ", pingstate->first ? "" : ", "); @@ -317,7 +318,7 @@ static void ping_cb(int result, int bytes, int psize, snprintf(line, sizeof(line), DBQ(rtt) ":%f", - usecs/1000.); + nsecs/1e6); add_str(pingstate, line); if (!pingstate->got_reply && result != PING_ERR_DUP) @@ -403,6 +404,16 @@ static void ping_cb(int result, int bytes, int psize, add_str(pingstate, line); report(pingstate); } + if (result == PING_ERR_BAD_ADDR) + { + pingstate->size= bytes; + pingstate->psize= psize; + snprintf(line, sizeof(line), + "%s{ " DBQ(error) ":" DBQ(address not allowed) " }", + pingstate->first ? "" : ", "); + add_str(pingstate, line); + report(pingstate); + } if (result == PING_ERR_DONE) { report(pingstate); @@ -462,7 +473,7 @@ static void fmticmp4(u_char *buffer, size_t *sizep, u_int8_t seq, struct icmp *icmp = (struct icmp *) buffer; struct evdata *data = (struct evdata *) (buffer + ICMP_MINLEN); - struct timeval now; + struct timespec now; minlen= sizeof(*data); if (*sizep < minlen) @@ -481,8 +492,8 @@ static void fmticmp4(u_char *buffer, size_t *sizep, u_int8_t seq, icmp->icmp_seq = htons(seq); /* message identifier */ /* User data */ - gettimeofday(&now, NULL); - data->ts = now; /* current time */ + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + data->ts = now; /* current uptime time */ data->index = idx; /* index into an array */ data->cookie= *cookiep; @@ -514,7 +525,7 @@ static void fmticmp6(u_char *buffer, size_t *sizep, struct icmp6_hdr *icmp = (struct icmp6_hdr *) buffer; struct evdata *data = (struct evdata *) (buffer + ICMP6_HDRSIZE); - struct timeval now; + struct timespec now; minlen= sizeof(*data); if (*sizep < minlen) @@ -531,8 +542,8 @@ static void fmticmp6(u_char *buffer, size_t *sizep, icmp->icmp6_seq = htons(seq); /* message identifier */ /* User data */ - gettimeofday(&now, NULL); - data->ts = now; /* current time */ + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + data->ts = now; /* current uptime time */ data->index = idx; /* index into an array */ data->cookie= *cookiep; @@ -666,7 +677,7 @@ static void ready_callback4 (int __attribute((unused)) unused, struct icmphdr * icmp; struct evdata * data; int hlen = 0; - struct timeval now; + struct timespec now; state= arg; base = state->base; @@ -676,7 +687,7 @@ static void ready_callback4 (int __attribute((unused)) unused, data = (struct evdata *) (base->packet + IPHDR + ICMP_MINLEN); /* Time the packet has been received */ - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); /* Receive data from the network */ nrecv = recvfrom(state->socket, base->packet, sizeof(base->packet), MSG_DONTWAIT, (struct sockaddr *) &remote, &slen); @@ -743,10 +754,16 @@ printf("ready_callback4: too short\n"); else if (icmp->type == ICMP_ECHOREPLY) { /* Use the User Data to relate Echo Request/Reply and evaluate the Round Trip Time */ - struct timeval elapsed; /* response time */ + struct timespec elapsed; /* response time */ /* Compute time difference to calculate the round trip */ - evutil_timersub (&now, &data->ts, &elapsed); + elapsed.tv_sec= now.tv_sec - data->ts.tv_sec; + if (now.tv_nsec < data->ts.tv_sec) + { + elapsed.tv_sec--; + now.tv_nsec += 1000000000; + } + elapsed.tv_nsec= now.tv_nsec - data->ts.tv_nsec; /* Set destination address of packet as local address */ sin4p= &loc_sin4; @@ -809,7 +826,7 @@ static void ready_callback6 (int __attribute((unused)) unused, struct icmp6_hdr *icmp; struct evdata * data; - struct timeval now; + struct timespec now; struct cmsghdr *cmsgptr; struct sockaddr_in6 *sin6p; struct msghdr msg; @@ -827,7 +844,7 @@ static void ready_callback6 (int __attribute((unused)) unused, offsetof(struct icmp6_hdr, icmp6_data16[2])); /* Time the packet has been received */ - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); iov[0].iov_base= base->packet; iov[0].iov_len= sizeof(base->packet); @@ -879,10 +896,16 @@ static void ready_callback6 (int __attribute((unused)) unused, else if (icmp->icmp6_type == ICMP6_ECHO_REPLY) { /* Use the User Data to relate Echo Request/Reply and evaluate the Round Trip Time */ - struct timeval elapsed; /* response time */ + struct timespec elapsed; /* response time */ /* Compute time difference to calculate the round trip */ - evutil_timersub (&now, &data->ts, &elapsed); + elapsed.tv_sec= now.tv_sec - data->ts.tv_sec; + if (now.tv_nsec < data->ts.tv_sec) + { + elapsed.tv_sec--; + now.tv_nsec += 1000000000; + } + elapsed.tv_nsec= now.tv_nsec - data->ts.tv_nsec; /* Set destination address of packet as local address */ memset(&loc_sin6, '\0', sizeof(loc_sin6)); @@ -1055,6 +1078,12 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[], free(lsa); return NULL; } + + if (atlas_check_addr(&lsa->u.sa, lsa->len) == -1) + { + free(lsa); + return NULL; + } } state= xzalloc(sizeof(*state)); @@ -1233,7 +1262,7 @@ static void ping_start2(void *state) static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) { - int count; + int r, count; struct pingstate *env; struct evutil_addrinfo *cur; @@ -1274,8 +1303,6 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) for (cur= res; cur; cur= cur->ai_next) count++; - // env->reportcount(env, count); - while (env->dns_curr) { env->socklen= env->dns_curr->ai_addrlen; @@ -1284,6 +1311,25 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) memcpy(&env->sin6, env->dns_curr->ai_addr, env->socklen); + r= atlas_check_addr((struct sockaddr *)&env->sin6, + env->socklen); + if (r == -1) + { + ping_cb(PING_ERR_BAD_ADDR, env->maxsize, -1, + NULL, 0, + (struct sockaddr *)NULL, 0, + 0, 0, NULL, + env); + ping_cb(PING_ERR_DONE, env->maxsize, -1, + (struct sockaddr *)NULL, 0, + (struct sockaddr *)NULL, 0, + 0, 0, NULL, + env); + if (env->base->done) + env->base->done(env); + return; + } + ping_start2(env); return; diff --git a/eperd/sslgetcert.c b/eperd/sslgetcert.c index fa3c254..91dea01 100644 --- a/eperd/sslgetcert.c +++ b/eperd/sslgetcert.c @@ -101,8 +101,8 @@ struct state int subid; int submax; time_t gstart; - struct timeval start; - struct timeval t_connect; + struct timespec start; + struct timespec t_connect; double resptime; FILE *post_fh; char *post_buf; @@ -133,6 +133,7 @@ struct state #define BUF_CHUNK 4096 +#define MSG_ALERT 21 #define MSG_HANDSHAKE 22 #define HS_CLIENT_HELLO 1 #define HS_SERVER_HELLO 2 @@ -355,7 +356,7 @@ static void msgbuf_add(struct msgbuf *msgbuf, void *buf, size_t size) buf_add(&msgbuf->buffer, buf, size); } -static int msgbuf_read(struct msgbuf *msgbuf, int type, +static int msgbuf_read(struct msgbuf *msgbuf, int *typep, char *majorp, char *minorp) { int r; @@ -377,12 +378,7 @@ static int msgbuf_read(struct msgbuf *msgbuf, int type, continue; } p= (uint8_t *)msgbuf->inbuf->buf+msgbuf->inbuf->offset; - type= p[0]; - if (p[0] != type) - { - fprintf(stderr, "msgbuf_read: got type %d\n", p[0]); - return -1; - } + *typep= p[0]; *majorp= p[1]; *minorp= p[2]; len= (p[3] << 8) + p[4]; @@ -522,10 +518,17 @@ static void add_ciphers(struct hsbuf *hsbuf) { uint8_t c; size_t len; - uint8_t ciphers[]= { 0x0,0xff, 0x0,0x88, 0x0,0x87, 0x0,0x39, 0x0,0x38, - 0x0,0x84, 0x0,0x35, 0x0,0x45, 0x0,0x44, 0x0,0x33, 0x0,0x32, - 0x0,0x96, 0x0,0x41, 0x0,0x4, 0x0,0x5, 0x0,0x2f, 0x0,0x16, - 0x0,0x13, 0xfe,0xff, 0x0,0xa }; + uint8_t ciphers[]= { + 0xc0,0x0a, /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ + 0xc0,0x09, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ + 0xc0,0x13, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */ + 0xc0,0x14, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ + 0x00,0x33, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ + 0x00,0x39, /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA */ + 0x00,0x2f, /* TLS_RSA_WITH_AES_128_CBC_SHA */ + 0x00,0x35, /* TLS_RSA_WITH_AES_256_CBC_SHA */ + 0x00,0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */ + }; len= sizeof(ciphers); @@ -872,6 +875,11 @@ static void readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) r= eat_server_hello(state); if (r == -1) return; + if (r == 1) + { + state->readstate= READ_DONE; + continue; + } state->readstate= READ_CERTS; continue; @@ -898,9 +906,164 @@ static void readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr) } } +static FILE *report_head(struct state *state) +{ + int major, minor; + const char *method; + FILE *fh; + double resptime; + struct timespec endtime; + char hostbuf[NI_MAXHOST]; + + clock_gettime(CLOCK_MONOTONIC_RAW, &endtime); + + fh= NULL; + if (state->output_file) + { + fh= fopen(state->output_file, "a"); + if (!fh) + { + crondlog(DIE9 "unable to append to '%s'", + state->output_file); + return NULL; + } + } + else + fh= stdout; + + fprintf(fh, "RESULT { "); + if (state->atlas) + { + fprintf(fh, DBQ(id) ":" DBQ(%s) + ", " DBQ(fw) ":%d" + ", " DBQ(lts) ":%d", + state->atlas, get_atlas_fw_version(), + get_timesync()); + } + + fprintf(fh, "%s" DBQ(time) ":%ld", + state->atlas ? ", " : "", time(NULL)); + fprintf(fh, ", " DBQ(dst_name) ":" DBQ(%s) ", " + DBQ(dst_port) ":" DBQ(%s), + state->hostname, state->portname); + + if (state->recv_major == 3 && state->recv_minor == 3) + { + method= "TLS"; + major= 1; + minor= 2; + } + else if (state->recv_major == 3 && state->recv_minor == 2) + { + method= "TLS"; + major= 1; + minor= 1; + } + else if (state->recv_major == 3 && state->recv_minor == 1) + { + method= "TLS"; + major= 1; + minor= 0; + } + else if (state->recv_major == 3 && state->recv_minor == 0) + { + method= "SSL"; + major= 3; + minor= 0; + } + else + { + method= "(unknown)"; + major= state->recv_major; + minor= state->recv_minor; + } + + fprintf(fh, ", " DBQ(method) ":" DBQ(%s) ", " + DBQ(ver) ":" DBQ(%d.%d), method, major, minor); + getnameinfo((struct sockaddr *)&state->sin6, state->socklen, + hostbuf, sizeof(hostbuf), NULL, 0, + NI_NUMERICHOST); + fprintf(fh, ", " DBQ(dst_addr) ":" DBQ(%s), hostbuf); + fprintf(fh, ", " DBQ(af) ": %d", + state->sin6.sin6_family == AF_INET6 ? 6 : 4); + + getnameinfo((struct sockaddr *)&state->loc_sin6, + state->loc_socklen, hostbuf, sizeof(hostbuf), NULL, 0, + NI_NUMERICHOST); + fprintf(fh, ", " DBQ(src_addr) ":" DBQ(%s), hostbuf); + + resptime= (state->t_connect.tv_sec- state->start.tv_sec)*1e3 + + (state->t_connect.tv_nsec-state->start.tv_nsec)/1e6; + fprintf(fh, ", " DBQ(ttc) ": %f", resptime); + + resptime= (endtime.tv_sec- state->start.tv_sec)*1e3 + + (endtime.tv_nsec-state->start.tv_nsec)/1e6; + fprintf(fh, ", " DBQ(rt) ": %f", resptime); + + return fh; +} + +static int eat_alert(struct state *state) +{ + int r, type, level, descr; + uint8_t *p; + struct msgbuf *msgbuf; + FILE *fh; + + msgbuf= &state->msginbuf; + + for (;;) + { + if (msgbuf->buffer.size - msgbuf->buffer.offset < 2) + { + r= msgbuf_read(msgbuf, &type, + &state->recv_major, &state->recv_minor); + if (r < 0) + { + if (errno != EAGAIN) + { + fprintf(stderr, + "eat_alert: msgbuf_read failed: %s\n", + strerror(errno)); + } + return -1; + } + if (type != MSG_ALERT) + { + fprintf(stderr, + "eat_alert: got bad type %d from msgbuf_read\n", + type); + return -1; + } + continue; + } + p= (uint8_t *)msgbuf->buffer.buf+msgbuf->buffer.offset; + level= p[0]; + descr= p[1]; + + fh= report_head(state); + if (!fh) + return -1; + + fprintf(fh, ", " DBQ(alert) ": { " DBQ(level) ": %d, " + DBQ(decription) ": %d }", + level, descr); + + msgbuf->buffer.offset += 2; + break; + } + + fprintf(fh, " }\n"); + + if (state->output_file) + fclose(fh); + + return 1; +} + static int eat_server_hello(struct state *state) { - int r; + int r, type; size_t len; uint8_t *p; struct msgbuf *msgbuf; @@ -911,7 +1074,7 @@ static int eat_server_hello(struct state *state) { if (msgbuf->buffer.size - msgbuf->buffer.offset < 4) { - r= msgbuf_read(msgbuf, MSG_HANDSHAKE, + r= msgbuf_read(msgbuf, &type, &state->recv_major, &state->recv_minor); if (r < 0) { @@ -920,6 +1083,20 @@ static int eat_server_hello(struct state *state) return -1; } + if (type == MSG_ALERT) + { + r= eat_alert(state); + if (r == 0) + continue; + return r; /* No need to continue */ + } + if (type != MSG_HANDSHAKE) + { + fprintf(stderr, + "eat_server_hello: got bad type %d from msgbuf_read\n", + type); + return -1; + } continue; } p= (uint8_t *)msgbuf->buffer.buf+msgbuf->buffer.offset; @@ -932,7 +1109,7 @@ static int eat_server_hello(struct state *state) len= (p[1] << 16) + (p[2] << 8) + p[3]; if (msgbuf->buffer.size - msgbuf->buffer.offset < 4+len) { - r= msgbuf_read(msgbuf, MSG_HANDSHAKE, + r= msgbuf_read(msgbuf, &type, &state->recv_major, &state->recv_minor); if (r < 0) { @@ -940,6 +1117,13 @@ static int eat_server_hello(struct state *state) "eat_server_hello: msgbuf_read failed\n"); return -1; } + if (type != MSG_HANDSHAKE) + { + fprintf(stderr, + "eat_server_hello: got bad type %d from msgbuf_read\n", + type); + return -1; + } continue; } msgbuf->buffer.offset += 4+len; @@ -950,16 +1134,12 @@ static int eat_server_hello(struct state *state) static int eat_certificate(struct state *state) { - int i, n, r, first, slen, need_nl, major, minor; + int i, n, r, first, slen, need_nl, type; size_t o, len; - const char *method; uint8_t *p; struct msgbuf *msgbuf; FILE *fh; - double resptime; - struct timeval endtime; struct buf tmpbuf; - char hostbuf[NI_MAXHOST]; msgbuf= &state->msginbuf; @@ -967,7 +1147,7 @@ static int eat_certificate(struct state *state) { if (msgbuf->buffer.size - msgbuf->buffer.offset < 4) { - r= msgbuf_read(msgbuf, MSG_HANDSHAKE, + r= msgbuf_read(msgbuf, &type, &state->recv_major, &state->recv_minor); if (r < 0) { @@ -979,6 +1159,13 @@ static int eat_certificate(struct state *state) } return -1; } + if (type != MSG_HANDSHAKE) + { + fprintf(stderr, + "eat_certificate: got bad type %d from msgbuf_read\n", + type); + return -1; + } continue; } p= (uint8_t *)msgbuf->buffer.buf+msgbuf->buffer.offset; @@ -990,7 +1177,7 @@ static int eat_certificate(struct state *state) len= (p[1] << 16) + (p[2] << 8) + p[3]; if (msgbuf->buffer.size - msgbuf->buffer.offset < 4+len) { - r= msgbuf_read(msgbuf, MSG_HANDSHAKE, + r= msgbuf_read(msgbuf, &type, &state->recv_major, &state->recv_minor); if (r < 0) { @@ -998,93 +1185,22 @@ static int eat_certificate(struct state *state) "eat_certificate: msgbuf_read failed\n"); return -1; } + if (type != MSG_HANDSHAKE) + { + fprintf(stderr, + "eat_certificate: got bad type %d from msgbuf_read\n", + type); + return -1; + } continue; } p += 4; n= (p[0] << 16) + (p[1] << 8) + p[2]; o= 3; - gettimeofday(&endtime, NULL); - - fh= NULL; - if (state->output_file) - { - fh= fopen(state->output_file, "a"); - if (!fh) - crondlog(DIE9 "unable to append to '%s'", - state->output_file); - } - else - fh= stdout; - - fprintf(fh, "RESULT { "); - if (state->atlas) - { - fprintf(fh, DBQ(id) ":" DBQ(%s) - ", " DBQ(fw) ":%d" - ", " DBQ(lts) ":%d", - state->atlas, get_atlas_fw_version(), - get_timesync()); - } - - fprintf(fh, "%s" DBQ(time) ":%ld", - state->atlas ? ", " : "", time(NULL)); - fprintf(fh, ", " DBQ(dst_name) ":" DBQ(%s) ", " - DBQ(dst_port) ":" DBQ(%s), - state->hostname, state->portname); - - if (state->recv_major == 3 && state->recv_minor == 3) - { - method= "TLS"; - major= 1; - minor= 2; - } - else if (state->recv_major == 3 && state->recv_minor == 2) - { - method= "TLS"; - major= 1; - minor= 1; - } - else if (state->recv_major == 3 && state->recv_minor == 1) - { - method= "TLS"; - major= 1; - minor= 0; - } - else if (state->recv_major == 3 && state->recv_minor == 0) - { - method= "SSL"; - major= 3; - minor= 0; - } - else - { - method= "(unknown)"; - major= state->recv_major; - minor= state->recv_minor; - } - - fprintf(fh, ", " DBQ(method) ":" DBQ(%s) ", " - DBQ(ver) ":" DBQ(%d.%d), method, major, minor); - getnameinfo((struct sockaddr *)&state->sin6, state->socklen, - hostbuf, sizeof(hostbuf), NULL, 0, - NI_NUMERICHOST); - fprintf(fh, ", " DBQ(dst_addr) ":" DBQ(%s), hostbuf); - fprintf(fh, ", " DBQ(af) ": %d", - state->sin6.sin6_family == AF_INET6 ? 6 : 4); - - getnameinfo((struct sockaddr *)&state->loc_sin6, - state->loc_socklen, hostbuf, sizeof(hostbuf), NULL, 0, - NI_NUMERICHOST); - fprintf(fh, ", " DBQ(src_addr) ":" DBQ(%s), hostbuf); - - resptime= (state->t_connect.tv_sec- state->start.tv_sec)*1e3 + - (state->t_connect.tv_usec-state->start.tv_usec)/1e3; - fprintf(fh, ", " DBQ(ttc) ": %f", resptime); - - resptime= (endtime.tv_sec- state->start.tv_sec)*1e3 + - (endtime.tv_usec-state->start.tv_usec)/1e3; - fprintf(fh, ", " DBQ(rt) ": %f", resptime); + fh= report_head(state); + if (fh == NULL) + return -1; first= 1; fprintf(fh, ", " DBQ(cert) ":[ "); @@ -1158,7 +1274,7 @@ static void writecb(struct bufferevent *bev, void *ptr) switch(state->writestate) { case WRITE_HELLO: - gettimeofday(&state->t_connect, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &state->t_connect); buf_init(&outbuf, bev); msgbuf_init(&msgoutbuf, NULL, &outbuf); @@ -1242,7 +1358,7 @@ static void beforeconnect(struct tu_env *env, //if (!state->do_all || !state->do_combine) state->reslen= 0; - gettimeofday(&state->start, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &state->start); } @@ -1292,6 +1408,12 @@ static void reporterr(struct tu_env *env, enum tu_err cause, report(state); break; + case TU_BAD_ADDR: + add_str(state, DBQ(error) ": " DBQ(address not allowed)); + state->dnserr= 1; + report(state); + break; + default: crondlog(DIE9 "reporterr: bad cause %d", cause); } diff --git a/eperd/tcputil.c b/eperd/tcputil.c index e1d4505..22885b0 100644 --- a/eperd/tcputil.c +++ b/eperd/tcputil.c @@ -63,6 +63,14 @@ void tu_restart_connect(struct tu_env *env) { evtimer_add(&env->timer, &env->interval); + r= atlas_check_addr(env->dns_curr->ai_addr, + env->dns_curr->ai_addrlen); + if (r == -1) + { + env->reporterr(env, TU_BAD_ADDR, ""); + return; + } + env->beforeconnect(env, env->dns_curr->ai_addr, env->dns_curr->ai_addrlen); @@ -166,6 +174,14 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) { evtimer_add(&env->timer, &env->interval); + r= atlas_check_addr(env->dns_curr->ai_addr, + env->dns_curr->ai_addrlen); + if (r == -1) + { + env->reporterr(env, TU_BAD_ADDR, ""); + return; + } + env->beforeconnect(env, env->dns_curr->ai_addr, env->dns_curr->ai_addrlen); diff --git a/eperd/tcputil.h b/eperd/tcputil.h index 1264299..89cfbcd 100644 --- a/eperd/tcputil.h +++ b/eperd/tcputil.h @@ -7,7 +7,7 @@ #include enum tu_err { TU_DNS_ERR, TU_READ_ERR, TU_SOCKET_ERR, TU_CONNECT_ERR, - TU_OUT_OF_ADDRS }; + TU_OUT_OF_ADDRS, TU_BAD_ADDR }; struct tu_env { char dnsip; diff --git a/eperd/traceroute.c b/eperd/traceroute.c index 26194c0..4875721 100644 --- a/eperd/traceroute.c +++ b/eperd/traceroute.c @@ -142,7 +142,7 @@ struct trtstate struct evutil_addrinfo *dns_curr; time_t starttime; - struct timeval xmit_time; + struct timespec xmit_time; struct event timer; @@ -185,7 +185,7 @@ struct v6info uint32_t pid; uint32_t id; uint32_t seq; - struct timeval tv; + struct timespec tv; }; static int create_socket(struct trtstate *state, int do_tcp); @@ -520,7 +520,7 @@ static void send_pkt(struct trtstate *state) } state->seq++; - gettimeofday(&state->xmit_time, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &state->xmit_time); if (state->sin6.sin6_family == AF_INET6) { @@ -1362,11 +1362,12 @@ static void ready_callback4(int __attribute((unused)) unused, struct tcphdr *etcp; struct udphdr *eudp; double ms; - struct timeval now, interval; + struct timespec now; + struct timeval interval; struct sockaddr_in remote; char line[80]; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); state= s; base= state->base; @@ -1510,7 +1511,7 @@ static void ready_callback4(int __attribute((unused)) unused, state->last_response_hop= state->hop; ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -1724,7 +1725,7 @@ printf("curpacksize: %d\n", state->curpacksize); state->last_response_hop= state->hop; ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -1952,7 +1953,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family state->last_response_hop= state->hop; ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -2223,7 +2224,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family } ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -2278,12 +2279,52 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family } } +static void report_hdropts(struct trtstate *state, unsigned char *s, + unsigned char *e) +{ + int o, len, mss; + unsigned char *orig_s; + char line[80]; + + add_str(state, ", " DBQ(hdropts) ": [ "); + orig_s= s; + while (s e) + { + printf("report_hdropts: bad option\n"); + break; + } + mss= (s[2] << 8) | s[3]; + snprintf(line, sizeof(line), + "%s{ " DBQ(mss) ":%d }", + s != orig_s ? ", " : "", mss); + add_str(state, line); + s += len; + continue; + default: + snprintf(line, sizeof(line), + "%s{ " DBQ(unknown-opt) ":%d }", + s != orig_s ? ", " : "", o); + add_str(state, line); + break; + } + break; + } + add_str(state, " ]"); +} + static void ready_tcp4(int __attribute((unused)) unused, const short __attribute((unused)) event, void *s) { uint16_t myport; socklen_t slen; - int hlen, late, isDup; + int hlen, late, isDup, tcp_hlen; unsigned ind, seq; ssize_t nrecv; struct trtbase *base; @@ -2291,12 +2332,13 @@ static void ready_tcp4(int __attribute((unused)) unused, struct ip *ip; double ms; struct tcphdr *tcphdr; + unsigned char *e, *p; struct sockaddr_in remote; - struct timeval now; + struct timespec now; struct timeval interval; char line[80]; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); state= s; base= state->base; @@ -2323,6 +2365,14 @@ static void ready_tcp4(int __attribute((unused)) unused, tcphdr= (struct tcphdr *)(base->packet+hlen); + tcp_hlen= tcphdr->doff * 4; + if (nrecv < hlen + tcp_hlen || tcphdr->doff < 5) + { + /* Short packet */ + printf("ready_tcp4: too short %d\n", (int)nrecv); + return; + } + /* Quick check if the port is in range */ myport= ntohs(tcphdr->dest); if (myport < SRC_BASE_PORT || myport > SRC_BASE_PORT+256) @@ -2389,7 +2439,7 @@ printf("got seq %d, expected %d\n", seq, state->seq); } ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -2407,6 +2457,13 @@ printf("got seq %d, expected %d\n", seq, state->seq); (tcphdr->urg ? "U" : "")); add_str(state, line); + if (tcp_hlen > sizeof(*tcphdr)) + { + p= (unsigned char *)&tcphdr[1]; + e= ((unsigned char *)tcphdr) + tcp_hlen; + report_hdropts(state, p, e); + } + if (!late) { snprintf(line, sizeof(line), ", \"rtt\":%.3f", ms); @@ -2446,25 +2503,26 @@ static void ready_tcp6(int __attribute((unused)) unused, const short __attribute((unused)) event, void *s) { uint16_t myport; - int late, isDup, rcvdttl; + int late, isDup, rcvdttl, tcp_hlen; unsigned ind, seq; ssize_t nrecv; struct trtbase *base; struct trtstate *state; double ms; + unsigned char *e, *p; struct tcphdr *tcphdr; struct cmsghdr *cmsgptr; struct msghdr msg; struct iovec iov[1]; struct sockaddr_in6 remote; struct in6_addr dstaddr; - struct timeval now; + struct timespec now; struct timeval interval; char buf[INET6_ADDRSTRLEN]; char line[80]; char cmsgbuf[256]; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); state= s; base= state->base; @@ -2509,6 +2567,14 @@ static void ready_tcp6(int __attribute((unused)) unused, tcphdr= (struct tcphdr *)(base->packet); + tcp_hlen= tcphdr->doff * 4; + if (nrecv < tcp_hlen || tcphdr->doff < 5) + { + /* Short packet */ + printf("ready_tcp6: too short %d\n", (int)nrecv); + return; + } + /* Quick check if the port is in range */ myport= ntohs(tcphdr->dest); if (myport < SRC_BASE_PORT || myport > SRC_BASE_PORT+256) @@ -2573,7 +2639,7 @@ printf("got seq %d, expected %d\n", seq, state->seq); } ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; snprintf(line, sizeof(line), "%s\"from\":\"%s\"", (late || isDup) ? ", " : "", @@ -2590,6 +2656,14 @@ printf("got seq %d, expected %d\n", seq, state->seq); (tcphdr->ack ? "A" : ""), (tcphdr->urg ? "U" : "")); add_str(state, line); + + if (tcp_hlen > sizeof(*tcphdr)) + { + p= (unsigned char *)&tcphdr[1]; + e= ((unsigned char *)tcphdr) + tcp_hlen; + report_hdropts(state, p, e); + } + if (!late) { snprintf(line, sizeof(line), ", \"rtt\":%.3f", ms); @@ -2644,7 +2718,7 @@ static void ready_callback6(int __attribute((unused)) unused, struct cmsghdr *cmsgptr; void *ptr; double ms; - struct timeval now; + struct timespec now; struct sockaddr_in6 remote; struct in6_addr dstaddr; struct msghdr msg; @@ -2654,7 +2728,7 @@ static void ready_callback6(int __attribute((unused)) unused, char line[80]; char cmsgbuf[256]; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); state= s; base= state->base; @@ -3015,14 +3089,13 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family if (!late) { ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/ - 1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/ + 1e6; } else if (v6info) { ms= (now.tv_sec-v6info->tv.tv_sec)*1000 + - (now.tv_usec-v6info->tv.tv_usec)/ - 1e3; + (now.tv_nsec-v6info->tv.tv_nsec)/1e6; } snprintf(line, sizeof(line), "%s\"from\":\"%s\"", @@ -3295,14 +3368,12 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family if (!late) { ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 + - (now.tv_usec-state->xmit_time.tv_usec)/ - 1e3; + (now.tv_nsec-state->xmit_time.tv_nsec)/1e6; } else { ms= (now.tv_sec-v6info->tv.tv_sec)*1000 + - (now.tv_usec-v6info->tv.tv_usec)/ - 1e3; + (now.tv_nsec-v6info->tv.tv_nsec)/1e6; } snprintf(line, sizeof(line), "%s\"from\":\"%s\"", @@ -3510,6 +3581,12 @@ for (i= 0; argv[i] != NULL; i++) free(lsa); return NULL; } + + if (atlas_check_addr(&lsa->u.sa, lsa->len) == -1) + { + free(lsa); + return NULL; + } } else { @@ -3547,6 +3624,8 @@ for (i= 0; argv[i] != NULL; i++) state->result= NULL; state->reslen= 0; state->resmax= 0; + state->socket_icmp= -1; + state->socket_tcp= -1; for (i= 0; itabsiz; i++) { @@ -3863,7 +3942,7 @@ static int create_socket(struct trtstate *state, int do_tcp) static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) { - int count; + int r, count; struct trtstate *env; struct evutil_addrinfo *cur; char line[160]; @@ -3915,6 +3994,24 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx) memcpy(&env->sin6, env->dns_curr->ai_addr, env->socklen); + r= atlas_check_addr((struct sockaddr *)&env->sin6, + env->socklen); + if (r == -1) + { + if (env->result) free(env->result); + env->resmax= 80; + env->result= xmalloc(env->resmax); + env->reslen= 0; + + env->starttime= time(NULL); + snprintf(line, sizeof(line), + "{ " DBQ(error) ":" DBQ(address not allowed) " }"); + add_str(env, line); + env->dnsip= 1; + report(env); + return; + } + traceroute_start2(env); evutil_freeaddrinfo(env->dns_res); -- cgit v1.2.3