aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eperd/eooqd.c32
-rw-r--r--eperd/eperd.c56
-rw-r--r--eperd/eperd.h4
-rw-r--r--eperd/evtdig.c142
-rw-r--r--eperd/httpget.c55
-rw-r--r--eperd/ntp.c62
-rw-r--r--eperd/ping.c90
-rw-r--r--eperd/sslgetcert.c334
-rw-r--r--eperd/tcputil.c16
-rw-r--r--eperd/tcputil.h2
-rw-r--r--eperd/traceroute.c153
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/Kbuild1
-rw-r--r--libbb/atlas_check_addr.c102
-rw-r--r--miscutils/crond.c935
-rw-r--r--miscutils/ooqd.c31
-rw-r--r--networking/atlasinit.c740
-rw-r--r--networking/atlasinit.h33
-rw-r--r--networking/rptaddr6.c493
-rw-r--r--networking/rptaddrs.c8
20 files changed, 847 insertions, 2443 deletions
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 <math.h>
#include <event2/dns.h>
#include <event2/event.h>
#include <event2/event_struct.h>
@@ -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<sizeof(value) && *p != '\0'; i++, p++)
+ {
+ offset= strlen(line2);
+ if (*p < 32 || *p == '"' || *p == '\\' ||
+ *p >= 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 <event2/event_struct.h>
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)
+ {
+ o= *s;
+ switch(o)
+ {
+ case 2:
+ len= s[1];
+ if (len < 4 || s+len > 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; i<trt_base->tabsiz; 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);
diff --git a/include/libbb.h b/include/libbb.h
index 98775ae..3c8ad56 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -316,6 +316,7 @@ extern int validate_atlas_id(const char *atlas_id);
extern int get_probe_id(void);
extern int get_timesync(void);
extern int bind_interface(int socket, int af, char *name);
+extern int atlas_check_addr(const struct sockaddr *sa, socklen_t len);
int ndelay_on(int fd) FAST_FUNC;
int ndelay_off(int fd) FAST_FUNC;
diff --git a/libbb/Kbuild b/libbb/Kbuild
index 0b77f72..9a17725 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -11,6 +11,7 @@ lib-y += ask_confirmation.o
lib-y += atlas_bb64.o
lib-y += atlas_probe.o
lib-y += atlas_timesync.o
+lib-y += atlas_check_addr.o
lib-y += bb_askpass.o
lib-y += bb_basename.o
lib-y += bb_do_delay.o
diff --git a/libbb/atlas_check_addr.c b/libbb/atlas_check_addr.c
new file mode 100644
index 0000000..ea6724d
--- /dev/null
+++ b/libbb/atlas_check_addr.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 RIPE NCC <atlas@ripe.net>
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+struct ipv4_prefix
+{
+ uint32_t addr;
+ unsigned len;
+}
+static bad_ipv4[] =
+{
+ { 0x7F000000, 8 }, /* 127.0.0.0/8 localhost */
+ { 0x0A000000, 8 }, /* 10.0.0.0/8 (RFC-1918) */
+ { 0xAC100000, 12 }, /* 172.16.0.0/12 (RFC-1918) */
+ { 0xC0A80000, 16 }, /* 192.168.0.0/16 (RFC-1918) */
+ { 0xA9FE0000, 16 }, /* 169.254.0.0/16 (RFC-3927) */
+ { 0xE0000000, 3 }, /* 224.0.0.0/3 multicast and reserved */
+};
+
+struct ipv6_prefix
+{
+ uint16_t addr[8];
+ unsigned len;
+}
+static bad_ipv6[] =
+{
+ { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001 },
+ 128 }, /* ::1 loopback */
+ { { 0xE000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ 3 }, /* e000::/3 ULA, link local, multicast */
+};
+
+int atlas_check_addr(const struct sockaddr *sa, socklen_t len)
+{
+ uint16_t addr2, mask2;
+ int i, j, prefix_len;
+ uint32_t addr4, mask4;
+ uint16_t *addr2p;
+ const struct sockaddr_in *sin4p;
+ const struct sockaddr_in6 *sin6p;
+
+ switch(sa->sa_family)
+ {
+ case AF_INET:
+ if (len < sizeof(*sin4p))
+ return -1;
+ sin4p= (const struct sockaddr_in *)sa;
+ addr4= sin4p->sin_addr.s_addr;
+ addr4= ntohl(addr4);
+ for (i= 0; i<sizeof(bad_ipv4)/sizeof(bad_ipv4[0]); i++)
+ {
+ mask4= ~((1ul << (32-bad_ipv4[i].len))-1);
+ if ((addr4 & mask4) == bad_ipv4[i].addr)
+ return -1;
+ }
+ return 0;
+
+ case AF_INET6:
+ if (len < sizeof(*sin6p))
+ return -1;
+ sin6p= (const struct sockaddr_in6 *)sa;
+ addr2p= (uint16_t *)&sin6p->sin6_addr;
+ for (i= 0; i<sizeof(bad_ipv6)/sizeof(bad_ipv6[0]); i++)
+ {
+ prefix_len= bad_ipv6[i].len;
+ for (j= 0; j<prefix_len; j += 16)
+ {
+ addr2= ntohs(addr2p[j/16]);
+ if (j+16 <= prefix_len)
+ {
+ /* Match entire word */
+ if (addr2 != bad_ipv6[i].addr[j/16])
+ {
+ /* Different prefix */
+ break;
+ }
+ continue;
+ }
+ mask2= ~((1ul << (16-(prefix_len % 16)))-1);
+ if ((addr2 & mask2) == bad_ipv6[i].addr[j/16])
+ {
+ return -1;
+ }
+ break;
+ }
+ if (j < prefix_len)
+ {
+ /* No match, try the next one */
+ continue;
+ }
+
+ /* Match */
+ return -1;
+ }
+ return 0;
+ }
+ return -1; /* Default to not allowed */
+}
+
diff --git a/miscutils/crond.c b/miscutils/crond.c
deleted file mode 100644
index 732fbb1..0000000
--- a/miscutils/crond.c
+++ /dev/null
@@ -1,935 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * crond -d[#] -c <crondir> -f -b
- *
- * run as root, but NOT setuid root
- *
- * Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com)
- * (version 2.3.2)
- * Vladimir Oleynik <dzo@simtreas.ru> (C) 2002
- *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- */
-
-#include "libbb.h"
-#include <syslog.h>
-
-/* glibc frees previous setenv'ed value when we do next setenv()
- * of the same variable. uclibc does not do this! */
-#if (defined(__GLIBC__) && !defined(__UCLIBC__)) /* || OTHER_SAFE_LIBC... */
-#define SETENV_LEAKS 0
-#else
-#define SETENV_LEAKS 1
-#endif
-
-
-#ifndef CRONTABS
-#define CRONTABS "/var/spool/cron/crontabs"
-#endif
-#ifndef TMPDIR
-#define TMPDIR "/var/spool/cron"
-#endif
-#ifndef SENDMAIL
-#define SENDMAIL "sendmail"
-#endif
-#ifndef SENDMAIL_ARGS
-#define SENDMAIL_ARGS "-ti", "oem"
-#endif
-#ifndef CRONUPDATE
-#define CRONUPDATE "cron.update"
-#endif
-#ifndef MAXLINES
-#define MAXLINES 256 /* max lines in non-root crontabs */
-#endif
-
-
-typedef struct CronFile {
- struct CronFile *cf_Next;
- struct CronLine *cf_LineBase;
- char *cf_User; /* username */
- smallint cf_Ready; /* bool: one or more jobs ready */
- smallint cf_Running; /* bool: one or more jobs running */
- smallint cf_Deleted; /* marked for deletion, ignore */
-} CronFile;
-
-typedef struct CronLine {
- struct CronLine *cl_Next;
- char *cl_Shell; /* shell command */
- pid_t cl_Pid; /* running pid, 0, or armed (-1) */
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
- int cl_MailPos; /* 'empty file' size */
- smallint cl_MailFlag; /* running pid is for mail */
- char *cl_MailTo; /* whom to mail results */
-#endif
- /* ordered by size, not in natural order. makes code smaller: */
- char cl_Dow[7]; /* 0-6, beginning sunday */
- char cl_Mons[12]; /* 0-11 */
- char cl_Hrs[24]; /* 0-23 */
- char cl_Days[32]; /* 1-31 */
- char cl_Mins[60]; /* 0-59 */
-} CronLine;
-
-
-#define DaemonUid 0
-
-
-enum {
- OPT_l = (1 << 0),
- OPT_L = (1 << 1),
- OPT_f = (1 << 2),
- OPT_b = (1 << 3),
- OPT_S = (1 << 4),
- OPT_c = (1 << 5),
- OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D,
-};
-#if ENABLE_FEATURE_CROND_D
-#define DebugOpt (option_mask32 & OPT_d)
-#else
-#define DebugOpt 0
-#endif
-
-
-struct globals {
- unsigned LogLevel; /* = 8; */
- const char *LogFile;
- const char *CDir; /* = CRONTABS; */
- CronFile *FileBase;
-#if SETENV_LEAKS
- char *env_var_user;
- char *env_var_home;
-#endif
-};
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define LogLevel (G.LogLevel )
-#define LogFile (G.LogFile )
-#define CDir (G.CDir )
-#define FileBase (G.FileBase )
-#define env_var_user (G.env_var_user )
-#define env_var_home (G.env_var_home )
-#define INIT_G() do { \
- LogLevel = 8; \
- CDir = CRONTABS; \
-} while (0)
-
-
-static void CheckUpdates(void);
-static void SynchronizeDir(void);
-static int TestJobs(time_t t1, time_t t2);
-static void RunJobs(void);
-static int CheckJobs(void);
-static void RunJob(const char *user, CronLine *line);
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
-static void EndJob(const char *user, CronLine *line);
-#else
-#define EndJob(user, line) ((line)->cl_Pid = 0)
-#endif
-static void DeleteFile(const char *userName);
-
-
-#define LVL5 "\x05"
-#define LVL7 "\x07"
-#define LVL8 "\x08"
-#define LVL9 "\x09"
-#define WARN9 "\x49"
-#define DIE9 "\xc9"
-/* level >= 20 is "error" */
-#define ERR20 "\x14"
-
-static void crondlog(const char *ctl, ...)
-{
- va_list va;
- int level = (ctl[0] & 0x1f);
-
- va_start(va, ctl);
- if (level >= (int)LogLevel) {
- /* Debug mode: all to (non-redirected) stderr, */
- /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
- if (!DebugOpt && LogFile) {
- /* Otherwise (log to file): we reopen log file at every write: */
- int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
- if (logfd >= 0)
- xmove_fd(logfd, STDERR_FILENO);
- }
-// TODO: ERR -> error, WARN -> warning, LVL -> info
- bb_verror_msg(ctl + 1, va, /* strerr: */ NULL);
- }
- va_end(va);
- if (ctl[0] & 0x80)
- exit(20);
-}
-
-int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int crond_main(int argc UNUSED_PARAM, char **argv)
-{
- unsigned opt;
-
- INIT_G();
-
- /* "-b after -f is ignored", and so on for every pair a-b */
- opt_complementary = "f-b:b-f:S-L:L-S" USE_FEATURE_CROND_D(":d-l")
- ":l+:d+"; /* -l and -d have numeric param */
- opt = getopt32(argv, "l:L:fbSc:" USE_FEATURE_CROND_D("d:"),
- &LogLevel, &LogFile, &CDir
- USE_FEATURE_CROND_D(,&LogLevel));
- /* both -d N and -l N set the same variable: LogLevel */
-
- if (!(opt & OPT_f)) {
- /* close stdin, stdout, stderr.
- * close unused descriptors - don't need them. */
- bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
- }
-
- if (!DebugOpt && LogFile == NULL) {
- /* logging to syslog */
- openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
- logmode = LOGMODE_SYSLOG;
- }
-
- xchdir(CDir);
- //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
- xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
- crondlog(LVL9 "crond (busybox "BB_VER") started, log level %d", LogLevel);
- SynchronizeDir();
-
- /* main loop - synchronize to 1 second after the minute, minimum sleep
- * of 1 second. */
- {
- time_t t1 = time(NULL);
- time_t t2;
- long dt;
- int rescan = 60;
- int sleep_time = 60;
-
- write_pidfile("/var/run/crond.pid");
- for (;;) {
- sleep((sleep_time + 1) - (time(NULL) % sleep_time));
-
- t2 = time(NULL);
- dt = (long)t2 - (long)t1;
-
- /*
- * The file 'cron.update' is checked to determine new cron
- * jobs. The directory is rescanned once an hour to deal
- * with any screwups.
- *
- * check for disparity. Disparities over an hour either way
- * result in resynchronization. A reverse-indexed disparity
- * less then an hour causes us to effectively sleep until we
- * match the original time (i.e. no re-execution of jobs that
- * have just been run). A forward-indexed disparity less then
- * an hour causes intermediate jobs to be run, but only once
- * in the worst case.
- *
- * when running jobs, the inequality used is greater but not
- * equal to t1, and less then or equal to t2.
- */
- if (--rescan == 0) {
- rescan = 60;
- SynchronizeDir();
- }
- CheckUpdates();
- if (DebugOpt)
- crondlog(LVL5 "wakeup dt=%ld", dt);
- if (dt < -60 * 60 || dt > 60 * 60) {
- crondlog(WARN9 "time disparity of %d minutes detected", dt / 60);
- } else if (dt > 0) {
- TestJobs(t1, t2);
- RunJobs();
- sleep(5);
- if (CheckJobs() > 0) {
- sleep_time = 10;
- } else {
- sleep_time = 60;
- }
- }
- t1 = t2;
- }
- }
- return 0; /* not reached */
-}
-
-#if SETENV_LEAKS
-/* We set environment *before* vfork (because we want to use vfork),
- * so we cannot use setenv() - repeated calls to setenv() may leak memory!
- * Using putenv(), and freeing memory after unsetenv() won't leak */
-static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, int len*/)
-{
- const int len = 4; /* both var names are 4 char long */
- char *var_val = *pvar_val;
-
- if (var_val) {
- var_val[len] = '\0'; /* nuke '=' */
- unsetenv(var_val);
- free(var_val);
- }
- *pvar_val = xasprintf("%s=%s", var, val);
- putenv(*pvar_val);
-}
-#endif
-
-static void SetEnv(struct passwd *pas)
-{
-#if SETENV_LEAKS
- safe_setenv4(&env_var_user, "USER", pas->pw_name);
- safe_setenv4(&env_var_home, "HOME", pas->pw_dir);
- /* if we want to set user's shell instead: */
- /*safe_setenv(env_var_user, "SHELL", pas->pw_shell, 5);*/
-#else
- xsetenv("USER", pas->pw_name);
- xsetenv("HOME", pas->pw_dir);
-#endif
- /* currently, we use constant one: */
- /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
-}
-
-static void ChangeUser(struct passwd *pas)
-{
- /* careful: we're after vfork! */
- change_identity(pas); /* - initgroups, setgid, setuid */
- if (chdir(pas->pw_dir) < 0) {
- crondlog(LVL9 "can't chdir(%s)", pas->pw_dir);
- if (chdir(TMPDIR) < 0) {
- crondlog(DIE9 "can't chdir(%s)", TMPDIR); /* exits */
- }
- }
-}
-
-static const char DowAry[] ALIGN1 =
- "sun""mon""tue""wed""thu""fri""sat"
- /* "Sun""Mon""Tue""Wed""Thu""Fri""Sat" */
-;
-
-static const char MonAry[] ALIGN1 =
- "jan""feb""mar""apr""may""jun""jul""aug""sep""oct""nov""dec"
- /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */
-;
-
-static void ParseField(char *user, char *ary, int modvalue, int off,
- const char *names, char *ptr)
-/* 'names' is a pointer to a set of 3-char abbreviations */
-{
- char *base = ptr;
- int n1 = -1;
- int n2 = -1;
-
- // this can't happen due to config_read()
- /*if (base == NULL)
- return;*/
-
- while (1) {
- int skip = 0;
-
- /* Handle numeric digit or symbol or '*' */
- if (*ptr == '*') {
- n1 = 0; /* everything will be filled */
- n2 = modvalue - 1;
- skip = 1;
- ++ptr;
- } else if (isdigit(*ptr)) {
- if (n1 < 0) {
- n1 = strtol(ptr, &ptr, 10) + off;
- } else {
- n2 = strtol(ptr, &ptr, 10) + off;
- }
- skip = 1;
- } else if (names) {
- int i;
-
- for (i = 0; names[i]; i += 3) {
- /* was using strncmp before... */
- if (strncasecmp(ptr, &names[i], 3) == 0) {
- ptr += 3;
- if (n1 < 0) {
- n1 = i / 3;
- } else {
- n2 = i / 3;
- }
- skip = 1;
- break;
- }
- }
- }
-
- /* handle optional range '-' */
- if (skip == 0) {
- goto err;
- }
- if (*ptr == '-' && n2 < 0) {
- ++ptr;
- continue;
- }
-
- /*
- * collapse single-value ranges, handle skipmark, and fill
- * in the character array appropriately.
- */
- if (n2 < 0) {
- n2 = n1;
- }
- if (*ptr == '/') {
- skip = strtol(ptr + 1, &ptr, 10);
- }
-
- /*
- * fill array, using a failsafe is the easiest way to prevent
- * an endless loop
- */
- {
- int s0 = 1;
- int failsafe = 1024;
-
- --n1;
- do {
- n1 = (n1 + 1) % modvalue;
-
- if (--s0 == 0) {
- ary[n1 % modvalue] = 1;
- s0 = skip;
- }
- if (--failsafe == 0) {
- goto err;
- }
- } while (n1 != n2);
-
- }
- if (*ptr != ',') {
- break;
- }
- ++ptr;
- n1 = -1;
- n2 = -1;
- }
-
- if (*ptr) {
- err:
- crondlog(WARN9 "user %s: parse error at %s", user, base);
- return;
- }
-
- if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */
- /* can't use crondlog, it inserts '\n' */
- int i;
- for (i = 0; i < modvalue; ++i)
- fprintf(stderr, "%d", (unsigned char)ary[i]);
- fputc('\n', stderr);
- }
-}
-
-static void FixDayDow(CronLine *line)
-{
- unsigned i;
- int weekUsed = 0;
- int daysUsed = 0;
-
- for (i = 0; i < ARRAY_SIZE(line->cl_Dow); ++i) {
- if (line->cl_Dow[i] == 0) {
- weekUsed = 1;
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(line->cl_Days); ++i) {
- if (line->cl_Days[i] == 0) {
- daysUsed = 1;
- break;
- }
- }
- if (weekUsed != daysUsed) {
- if (weekUsed)
- memset(line->cl_Days, 0, sizeof(line->cl_Days));
- else /* daysUsed */
- memset(line->cl_Dow, 0, sizeof(line->cl_Dow));
- }
-}
-
-static void SynchronizeFile(const char *fileName)
-{
- struct parser_t *parser;
- struct stat sbuf;
- int maxLines;
- char *tokens[6];
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
- char *mailTo = NULL;
-#endif
-
- if (!fileName)
- return;
-
- DeleteFile(fileName);
- parser = config_open(fileName);
- if (!parser)
- return;
-
- maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES;
-
- if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DaemonUid) {
- CronFile *file = xzalloc(sizeof(CronFile));
- CronLine **pline;
- int n;
-
- file->cf_User = xstrdup(fileName);
- pline = &file->cf_LineBase;
-
- while (1) {
- CronLine *line;
-
- if (!--maxLines)
- break;
- n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY);
- if (!n)
- break;
-
- if (DebugOpt)
- crondlog(LVL5 "user:%s entry:%s", fileName, parser->data);
-
- /* check if line is setting MAILTO= */
- if (0 == strncmp(tokens[0], "MAILTO=", 7)) {
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
- free(mailTo);
- mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL;
-#endif /* otherwise just ignore such lines */
- continue;
- }
- /* check if a minimum of tokens is specified */
- if (n < 6)
- continue;
- *pline = line = xzalloc(sizeof(*line));
- /* parse date ranges */
- ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, tokens[0]);
- ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, tokens[1]);
- ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, tokens[2]);
- ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, tokens[3]);
- ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, tokens[4]);
- /*
- * fix days and dow - if one is not "*" and the other
- * is "*", the other is set to 0, and vise-versa
- */
- FixDayDow(line);
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
- /* copy mailto (can be NULL) */
- line->cl_MailTo = xstrdup(mailTo);
-#endif
- /* copy command */
- line->cl_Shell = xstrdup(tokens[5]);
- if (DebugOpt) {
- crondlog(LVL5 " command:%s", tokens[5]);
- }
- pline = &line->cl_Next;
-//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
- }
- *pline = NULL;
-
- file->cf_Next = FileBase;
- FileBase = file;
-
- if (maxLines == 0) {
- crondlog(WARN9 "user %s: too many lines", fileName);
- }
- }
- config_close(parser);
-}
-
-static void CheckUpdates(void)
-{
- FILE *fi;
- char buf[256];
-
- fi = fopen_for_read(CRONUPDATE);
- if (fi != NULL) {
- unlink(CRONUPDATE);
- while (fgets(buf, sizeof(buf), fi) != NULL) {
- /* use first word only */
- SynchronizeFile(strtok(buf, " \t\r\n"));
- }
- fclose(fi);
- }
-}
-
-static void SynchronizeDir(void)
-{
- CronFile *file;
- /* Attempt to delete the database. */
- again:
- for (file = FileBase; file; file = file->cf_Next) {
- if (!file->cf_Deleted) {
- DeleteFile(file->cf_User);
- goto again;
- }
- }
-
- /*
- * Remove cron update file
- *
- * Re-chdir, in case directory was renamed & deleted, or otherwise
- * screwed up.
- *
- * scan directory and add associated users
- */
- unlink(CRONUPDATE);
- if (chdir(CDir) < 0) {
- crondlog(DIE9 "can't chdir(%s)", CDir);
- }
- {
- DIR *dir = opendir(".");
- struct dirent *den;
-
- if (!dir)
- crondlog(DIE9 "can't chdir(%s)", "."); /* exits */
- while ((den = readdir(dir)) != NULL) {
- if (strchr(den->d_name, '.') != NULL) {
- continue;
- }
- if (getpwnam(den->d_name)) {
- SynchronizeFile(den->d_name);
- } else {
- crondlog(LVL7 "ignoring %s", den->d_name);
- }
- }
- closedir(dir);
- }
-}
-
-/*
- * DeleteFile() - delete user database
- *
- * Note: multiple entries for same user may exist if we were unable to
- * completely delete a database due to running processes.
- */
-static void DeleteFile(const char *userName)
-{
- CronFile **pfile = &FileBase;
- CronFile *file;
-
- while ((file = *pfile) != NULL) {
- if (strcmp(userName, file->cf_User) == 0) {
- CronLine **pline = &file->cf_LineBase;
- CronLine *line;
-
- file->cf_Running = 0;
- file->cf_Deleted = 1;
-
- while ((line = *pline) != NULL) {
- if (line->cl_Pid > 0) {
- file->cf_Running = 1;
- pline = &line->cl_Next;
- } else {
- *pline = line->cl_Next;
- free(line->cl_Shell);
- free(line);
- }
- }
- if (file->cf_Running == 0) {
- *pfile = file->cf_Next;
- free(file->cf_User);
- free(file);
- } else {
- pfile = &file->cf_Next;
- }
- } else {
- pfile = &file->cf_Next;
- }
- }
-}
-
-/*
- * TestJobs()
- *
- * determine which jobs need to be run. Under normal conditions, the
- * period is about a minute (one scan). Worst case it will be one
- * hour (60 scans).
- */
-static int TestJobs(time_t t1, time_t t2)
-{
- int nJobs = 0;
- time_t t;
-
- /* Find jobs > t1 and <= t2 */
-
- for (t = t1 - t1 % 60; t <= t2; t += 60) {
- struct tm *tp;
- CronFile *file;
- CronLine *line;
-
- if (t <= t1)
- continue;
-
- tp = localtime(&t);
- for (file = FileBase; file; file = file->cf_Next) {
- if (DebugOpt)
- crondlog(LVL5 "file %s:", file->cf_User);
- if (file->cf_Deleted)
- continue;
- for (line = file->cf_LineBase; line; line = line->cl_Next) {
- if (DebugOpt)
- crondlog(LVL5 " line %s", line->cl_Shell);
- if (line->cl_Mins[tp->tm_min] && line->cl_Hrs[tp->tm_hour]
- && (line->cl_Days[tp->tm_mday] || line->cl_Dow[tp->tm_wday])
- && line->cl_Mons[tp->tm_mon]
- ) {
- if (DebugOpt) {
- crondlog(LVL5 " job: %d %s",
- (int)line->cl_Pid, line->cl_Shell);
- }
- if (line->cl_Pid > 0) {
- crondlog(LVL8 "user %s: process already running: %s",
- file->cf_User, line->cl_Shell);
- } else if (line->cl_Pid == 0) {
- line->cl_Pid = -1;
- file->cf_Ready = 1;
- ++nJobs;
- }
- }
- }
- }
- }
- return nJobs;
-}
-
-static void RunJobs(void)
-{
- CronFile *file;
- CronLine *line;
-
- for (file = FileBase; file; file = file->cf_Next) {
- if (!file->cf_Ready)
- continue;
-
- file->cf_Ready = 0;
- for (line = file->cf_LineBase; line; line = line->cl_Next) {
- if (line->cl_Pid >= 0)
- continue;
-
- RunJob(file->cf_User, line);
- crondlog(LVL8 "USER %s pid %3d cmd %s",
- file->cf_User, (int)line->cl_Pid, line->cl_Shell);
- if (line->cl_Pid < 0) {
- file->cf_Ready = 1;
- } else if (line->cl_Pid > 0) {
- file->cf_Running = 1;
- }
- }
- }
-}
-
-/*
- * CheckJobs() - check for job completion
- *
- * Check for job completion, return number of jobs still running after
- * all done.
- */
-static int CheckJobs(void)
-{
- CronFile *file;
- CronLine *line;
- int nStillRunning = 0;
-
- for (file = FileBase; file; file = file->cf_Next) {
- if (file->cf_Running) {
- file->cf_Running = 0;
-
- for (line = file->cf_LineBase; line; line = line->cl_Next) {
- int status, r;
- if (line->cl_Pid <= 0)
- continue;
-
- r = waitpid(line->cl_Pid, &status, WNOHANG);
- if (r < 0 || r == line->cl_Pid) {
- EndJob(file->cf_User, line);
- if (line->cl_Pid) {
- file->cf_Running = 1;
- }
- } else if (r == 0) {
- file->cf_Running = 1;
- }
- }
- }
- nStillRunning += file->cf_Running;
- }
- return nStillRunning;
-}
-
-#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
-
-// TODO: sendmail should be _run-time_ option, not compile-time!
-
-static void
-ForkJob(const char *user, CronLine *line, int mailFd,
- const char *prog, const char *cmd, const char *arg,
- const char *mail_filename)
-{
- struct passwd *pas;
- pid_t pid;
-
- /* prepare things before vfork */
- pas = getpwnam(user);
- if (!pas) {
- crondlog(LVL9 "can't get uid for %s", user);
- goto err;
- }
- SetEnv(pas);
-
- pid = vfork();
- if (pid == 0) {
- /* CHILD */
- /* change running state to the user in question */
- ChangeUser(pas);
- if (DebugOpt) {
- crondlog(LVL5 "child running %s", prog);
- }
- if (mailFd >= 0) {
- xmove_fd(mailFd, mail_filename ? 1 : 0);
- dup2(1, 2);
- }
- /* crond 3.0pl1-100 puts tasks in separate process groups */
- bb_setpgrp();
- execlp(prog, prog, cmd, arg, NULL);
- crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user, prog, cmd, arg);
- if (mail_filename) {
- fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
- }
- _exit(EXIT_SUCCESS);
- }
-
- line->cl_Pid = pid;
- if (pid < 0) {
- /* FORK FAILED */
- crondlog(ERR20 "can't vfork");
- err:
- line->cl_Pid = 0;
- if (mail_filename) {
- unlink(mail_filename);
- }
- } else if (mail_filename) {
- /* PARENT, FORK SUCCESS
- * rename mail-file based on pid of process
- */
- char mailFile2[128];
-
- snprintf(mailFile2, sizeof(mailFile2), "%s/cron.%s.%d", TMPDIR, user, pid);
- rename(mail_filename, mailFile2); // TODO: xrename?
- }
-
- /*
- * Close the mail file descriptor.. we can't just leave it open in
- * a structure, closing it later, because we might run out of descriptors
- */
- if (mailFd >= 0) {
- close(mailFd);
- }
-}
-
-static void RunJob(const char *user, CronLine *line)
-{
- char mailFile[128];
- int mailFd = -1;
-
- line->cl_Pid = 0;
- line->cl_MailFlag = 0;
-
- if (line->cl_MailTo) {
- /* open mail file - owner root so nobody can screw with it. */
- snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid());
- mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);
-
- if (mailFd >= 0) {
- line->cl_MailFlag = 1;
- fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", line->cl_MailTo,
- line->cl_Shell);
- line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR);
- } else {
- crondlog(ERR20 "cannot create mail file %s for user %s, "
- "discarding output", mailFile, user);
- }
- }
-
- ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);
-}
-
-/*
- * EndJob - called when job terminates and when mail terminates
- */
-static void EndJob(const char *user, CronLine *line)
-{
- int mailFd;
- char mailFile[128];
- struct stat sbuf;
-
- /* No job */
- if (line->cl_Pid <= 0) {
- line->cl_Pid = 0;
- return;
- }
-
- /*
- * End of job and no mail file
- * End of sendmail job
- */
- snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, line->cl_Pid);
- line->cl_Pid = 0;
-
- if (line->cl_MailFlag == 0) {
- return;
- }
- line->cl_MailFlag = 0;
-
- /*
- * End of primary job - check for mail file. If size has increased and
- * the file is still valid, we sendmail it.
- */
- mailFd = open(mailFile, O_RDONLY);
- unlink(mailFile);
- if (mailFd < 0) {
- return;
- }
-
- if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid
- || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos
- || !S_ISREG(sbuf.st_mode)
- ) {
- close(mailFd);
- return;
- }
- if (line->cl_MailTo)
- ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL);
-}
-
-#else /* crond without sendmail */
-
-static void RunJob(const char *user, CronLine *line)
-{
- struct passwd *pas;
- pid_t pid;
-
- /* prepare things before vfork */
- pas = getpwnam(user);
- if (!pas) {
- crondlog(LVL9 "can't get uid for %s", user);
- goto err;
- }
- SetEnv(pas);
-
- /* fork as the user in question and run program */
- pid = vfork();
- if (pid == 0) {
- /* CHILD */
- /* change running state to the user in question */
- ChangeUser(pas);
- if (DebugOpt) {
- crondlog(LVL5 "child running %s", DEFAULT_SHELL);
- }
- /* crond 3.0pl1-100 puts tasks in separate process groups */
- bb_setpgrp();
- execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
- crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user,
- DEFAULT_SHELL, "-c", line->cl_Shell);
- _exit(EXIT_SUCCESS);
- }
- if (pid < 0) {
- /* FORK FAILED */
- crondlog(ERR20 "can't vfork");
- err:
- pid = 0;
- }
- line->cl_Pid = pid;
-}
-
-#endif /* ENABLE_FEATURE_CROND_CALL_SENDMAIL */
diff --git a/miscutils/ooqd.c b/miscutils/ooqd.c
index 4317e05..85114c9 100644
--- a/miscutils/ooqd.c
+++ b/miscutils/ooqd.c
@@ -29,6 +29,7 @@ int ooqd_main(int argc, char *argv[])
{
char *queue_file;
FILE *file;
+ struct stat sb;
char curr_qfile[256];
if (argc != 2)
@@ -50,17 +51,37 @@ int ooqd_main(int argc, char *argv[])
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 (stat(queue_file, &sb) == -1)
{
if (errno == ENOENT)
{
sleep(WAIT_TIME);
continue;
}
+ report_err("stat failed");
+ return 1;
+ }
+
+ /* 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(curr_qfile) == -1)
+ {
+ /* Expect ENOENT */
+ if (errno != ENOENT)
+ {
+ report_err("unlink failed");
+ return 1;
+ }
+ }
+
+ /* 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)
+ {
report_err("rename failed");
return 1;
}
diff --git a/networking/atlasinit.c b/networking/atlasinit.c
deleted file mode 100644
index 121b508..0000000
--- a/networking/atlasinit.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/* RIPEAtlas
- * All the configurable variables - and some non configurables too
- * Usage1: ./init_resp_parse < init_messagefile
- * Usage2: ./init_resp_parse init_messagefile
- * $Id: $
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <stdarg.h>
-#include "atlasinit.h"
-
-//#ifndef NOTBUSYBOX
-/* compiled to busybox. tested on 1.13 */
-#include "libbb.h"
-//#endif
-
-#define ERROR 1
-#define INFO 2
-#define ATLAS_DEFAULT_WAIT 100
-#define OPT_STRING "rcdsi:I:"
-#define ATLAS_WAIT 0
-
-enum
-{
- OPT_REG_INIT = (1 << 0), /* r */
- OPT_CNT_INIT = (1 << 1), /* c */
- OPT_CNT_HELLO = (1 << 2), /* d */
- OPT_SINCELAST = (1 << 3), /* s */
- OPT_P_TO_R_INIT = (1 << 4), /* i */
-};
-
-#define DBQ(str) "\"" #str "\""
-
-/*********************************************************************
- * Set these constants to your liking
- */
-static int read_wait (FILE *read_from, const char *type, int waittime);
-static int reg_init_main( int argc, char *argv[] );
-static int con_hello_main( int argc, char *argv[] );
-static int con_init_main( int argc, char *argv[] );
-static void since_last_main (int argc, char *argv[]);
-static void print_token_ver (FILE * write_to, int flag_rereg);
-
-const char atlas_log_file[]="./probe.log";
-const int atlas_log_level=INFO;
-
-const char atlas_contr_known_hosts[]="./known_hosts_controllers";
-const char atlas_rereg_timestamp[]="./rereg_time.sh";
-const char atlas_con_hello[]="./con_hello.txt";
-const char atlas_con_session_id[]="./con_session_id.txt";
-const char atlas_force_reg[] = "./force_reg.sh";
-const char atlas_netconfig_v4[] = "./netconfig_v4.vol";
-const char atlas_netconfig_v6[] = "./netconfig_v6.vol";
-const char atlas_resolv_conf[] = "./resolv.conf.vol";
-const char atlas_network_v4_info[] = "/home/atlas/status/network_v4_info.txt";
-const char atlas_network_v4_static_info[] = "/home/atlas/status/network_v4_static_info.txt";
-const char atlas_network_v4_static_info_json[] = "/home/atlas/status/network_v4_static_info.json";
-const char atlas_network_v6_static_info[] = "/home/atlas/status/network_v6_static_info.txt";
-const char atlas_network_v6_static_info_json[] = "/home/atlas/status/network_v6_static_info.json";
-const char atlas_network_dns_static_info[] = "/home/atlas/status/network_dns_static_info.txt";
-const char atlas_network_dns_static_info_json[] = "/home/atlas/status/network_dns_static_info.json";
-
-const int max_lines = 16; /* maximum lines we'll process */
-const int min_rereg_time = 100;
-const int max_rereg_time = 28*24*3600; /* 28d */
-const int default_rereg_time = 7*24*3600; /* 7d */
-char *str_reason;
-const char *str_device;
-
-/**********************************************************************/
-
-static char line[ATLAS_BUF_SIZE];
-
-#ifdef NOTBUSYBOX
-int main( int argc, char *argv[] )
-#else
-int atlasinit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int atlasinit_main( int argc, char *argv[] )
-#endif
-{
- int opt = 0;
-
- if(argc > 1)
- {
- str_device= NULL;
- opt = getopt32(argv, OPT_STRING, &str_reason, &str_device);
- argv += optind;
- argc -= optind;
- argc++; // AA Hack
- }
- else
- { // AA improve
- // we are called without an option decide which is default
- reg_init_main( argc, argv);
- }
-
- if(opt & OPT_REG_INIT)
- {
- reg_init_main( argc, argv);
- }
- else if(opt & OPT_CNT_HELLO)
- {
- con_hello_main(argc, argv);
- }
- else if ( opt & OPT_CNT_INIT)
- {
- con_init_main(argc, argv);
-
- }
- else if (opt & OPT_SINCELAST)
- {
- since_last_main(argc, argv);
- }
- else if(opt & OPT_P_TO_R_INIT)
- {
- print_token_ver(stdout, 1);
- }
-
- return 0;
-}
-
-static void print_token_ver (FILE * write_to, int flag_rereg)
-{
-float root_fs_ver = 0;
-FILE *fp = xfopen_for_read("/proc/version");
-FILE *fpv = fopen("/home/atlas/state/FIRMWARE_APPS_VERSION", "r");
- char *my_mac ;
-
-bzero( line, ATLAS_BUF_SIZE );
-fscanf (fp, "%s", line);
-fscanf (fp, "%s", line);
-fscanf (fp, "%s", line);
-if(fpv)
- fscanf (fpv, "%f", &root_fs_ver);
- else
- root_fs_ver=3100;
- if(flag_rereg > 0)
- fprintf(write_to, "P_TO_R_INIT\n");
- my_mac = getenv("ETHER_SCANNED");
- fprintf(write_to, "TOKEN_SPECS probev1 %s", line);
- if (my_mac != NULL)
- fprintf(write_to, "-%s ", my_mac );
- fprintf(write_to, " %d\n", (int)root_fs_ver);
- if(flag_rereg > 0)
- fprintf(write_to, "REASON_FOR_REGISTRATION %s\n", str_reason);
- fclose(fp);
-}
-
-static void since_last_main (int argc, char *argv[])
-{
- FILE *thenfile;
- int then;
- time_t mytime;
-
- mytime = time(0);
-
- if ( argc == 1) {
- printf("%d\n", (int)mytime);
- }
- else {
- if ((thenfile = fopen(argv[0], "r")) == NULL) {
- printf("%d\n", (int)mytime);
- }
- else {
- fscanf(thenfile, "%d", &then);
- printf("%d\n", (int)(mytime - then));
- }
- }
-}
-
-static int con_hello_main( int argc, char *argv[] )
-{
- /* read response from P_TO_C_HELLO */
- FILE *read_from = stdin;
- int ret = 0;
- long tmp_long;
-
- time_t mytime = time(0);
- time_t con_time;
- if( argc > 1 ) {
- read_from = fopen( argv[0], "rt" );
- if( read_from==NULL ) {
- atlas_log( ERROR, "Cannot read from file %s\n", argv[1] );
- return 1;
- }
- }
- /* read OK */
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
-
- if( strncmp(line,"OK\n",3) == 0 ) {
- int l=1;
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- while( !feof(read_from) && l<=max_lines ) {
- if( strncmp(line,"CONTROLLER_TIMESTAMP ", 21)==0 ) {
- int timediff2 ;
-
- sscanf( line+21, "%ld", &tmp_long);
- con_time= tmp_long;
- timediff2 = ( mytime - con_time ) * ( mytime - con_time );
- printf ("Mytime %d controller time %d\n",(int)mytime , (int)con_time);
- if( timediff2 > 4 ) {
- struct timeval tval;
-
- atlas_log( INFO, "Time difference is %d seconds, set time ?\n", timediff2);
- printf ("Set mytime \n");
- tval.tv_sec = con_time;
- tval.tv_usec = 0;
- settimeofday( &tval, NULL);
- }
-
- }
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- l++;
- }
- }
- else {
- fprintf (stderr, "P_TO_C_HELLO response is unexptedte %s\n", line);
- }
-
- if (argc > 1 )
- fclose (read_from);
- return ret;
-}
-static int con_init_main( int argc, char *argv[] )
-{
- FILE *read_from = stdin;
- int ret = 0;
-
- int remote_port;
- if( argc > 1 ) {
- read_from = fopen( argv[0], "rt" );
- if( read_from==NULL ) {
- atlas_log( ERROR, "Cannot read from file %s\n", argv[1] );
- return 1;
- }
- }
- /* read OK */
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
-
- if( strncmp(line,"OK\n",3) == 0 ) {
- int l=1;
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- while( !feof(read_from) && l<=max_lines ) {
- if( strncmp(line,"REMOTE_PORT", 11)==0 ) {
- sscanf( line+11, "%d", &remote_port);
- printf ("REMOTE_PORT=%d\n", remote_port);
- }
- else if ( strncmp(line,"SESSION_ID", 10)==0 )
- {
- FILE *f = fopen( atlas_con_hello, "wt" );
- FILE *f1 = fopen( atlas_con_session_id, "wt" );
-
- fprintf (f, "P_TO_C_HELLO\nSESSION_ID %s", line+11);
- fprintf (f1, "\nSESSION_ID %s\n", line+11);
- print_token_ver (f, 0 );
- fclose (f);
- fclose (f1);
-
- }
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- l++;
- }
- }
- else if (strncmp(line,"WAIT\n",5) == 0 )
- {
- read_wait(read_from, "CON_WAIT_TIMER", ATLAS_WAIT);
- }
- else if (strncmp(line,"REFUSED\n",8) == 0 )
- {
- FILE *f = fopen( atlas_force_reg, "wt" );
-
- unlink(atlas_con_hello);
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- fprintf (f,"REASON=%s\n", line+8);
- fclose(f);
-
- }
- else {
- char *p = strchr(line,'\n');
- if( p!=NULL ) *p = '\0';
- atlas_log( ERROR, "OK expected, got \"%s\" instead\n", line );
- read_wait(read_from, "CON_WAIT_TIMER", ATLAS_DEFAULT_WAIT); /* we got error the only action from probe is wait. so force it*/
- ret = 1;
- }
-
- if (argc > 1 )
- fclose (read_from);
- return ret;
-
-}
-static int read_wait (FILE *read_from, const char *type, int waittime)
-{
- unsigned delay;
- time_t mytime = time(0);
- if(waittime < 1)
- {
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- if( strncmp(line,"TIMEOUT", 7)==0 ) {
- sscanf( line+7, "%d", &delay);
- }
- else
- {
- delay = ATLAS_DEFAULT_WAIT;
- }
- }
- else
- {
- delay = waittime;
- }
- mytime = time(0);
- if(delay > max_rereg_time ) {
- atlas_log( ERROR, "Reregister time %d is too high\n", delay );
- delay = max_rereg_time;
- }
- if(delay < min_rereg_time ) {
- atlas_log( ERROR, "Reregister time %d is too high\n", delay );
- delay = min_rereg_time;
- }
- printf ("%s=%u\n", type, (uint)(mytime + delay));
- return (delay);
-}
-
-static int reg_init_main( int argc, char *argv[] )
-{
-
- time_t mytime;
- FILE *read_from = stdin;
-
- char *token;
- const char *search = " ";
- const char *search_nl = " \n";
- int ret = 0;
- int first;
-
- int reregister_time = default_rereg_time;
- mytime = time(NULL);
-
- if (!str_device)
- str_device= "eth0";
-
- if( argc >1 ) {
- read_from = fopen( argv[0], "rt" );
- if( read_from==NULL ) {
- atlas_log( ERROR, "Cannot read from file %s\n", argv[1] );
- return 1;
- }
- }
-
- /* read OK */
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
-
- if( strncmp(line,"OK\n",3) == 0 ) {
- int l=1;
- int n_controller = 0;
- char *host_name;
- char *type;
- char *key;
- int do_rm_v4_static_info;
- int do_rm_v6_static_info;
- int do_rm_dns_static_info;
-
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
-
- do_rm_v4_static_info= 1;
- do_rm_v6_static_info= 1;
- do_rm_dns_static_info= 1;
- while( !feof(read_from) && l<=max_lines ) {
- if( strncmp(line,"CONTROLLER ", 11)==0 ) {
- FILE *f;
- char *ptr;
-
- n_controller++;
- /* TODO: one can check whether it's about the right length and syntax */
-
- ptr = strchr( line+11, ' ' );
- if( ptr==NULL ) {
- atlas_log( ERROR, "CONTROLLER line is suspicious (line %d)\n", l );
- return 1;
- }
- f = fopen( atlas_contr_known_hosts, "wt" );
- if( f==NULL ) {
- atlas_log( ERROR, "Unable to append to file %s\n", atlas_contr_known_hosts );
- return 1;
- }
- //fprintf( f, "%s\n", line+11 );
- token = strtok(line+11, search);
- /* host name */
- printf ("CONTROLLER_%d_HOST=%s\n", n_controller, token);
- fprintf( f, "%s ", token);
- host_name = token;
-
- token = strtok(NULL, search);
- printf ("CONTROLLER_%d_PORT=%s\n", n_controller, token);
- token = strtok(NULL, search);
- fprintf( f, "%s ", token);
- type = token;
- token = strtok(NULL, search);
- fprintf( f, "%s\n", token);
- key = token;
- fprintf (f, "ipv4.%s %s %s\n", host_name, type, key);
- fprintf (f, "ipv6.%s %s %s\n", host_name, type, key);
- fclose(f);
-
- }
- else if( strncmp(line,"REREGISTER ", 11)==0 )
- {
- sscanf( line+11, "%d", &reregister_time );
- read_wait(read_from, "REREG_TIMER", reregister_time);
-
- }
- else if( strncmp(line,"REGSERVER_TIMESTAMP ", 20)==0 ) {
- int regserver_time;
- int timediff2 ;
-
- sscanf( line+20, "%d", &regserver_time );
- timediff2 = ( mytime - regserver_time ) * ( mytime - regserver_time );
- if( timediff2 > 4 ) {
- struct timeval tval;
-
- atlas_log( INFO, "Time difference is %d seconds, what to do now?\n", (int)(mytime-regserver_time) );
-
- tval.tv_sec = regserver_time;
- tval.tv_usec = 0;
- settimeofday( &tval, NULL);
- }
- }
- else if( strncmp(line,"FIRMWARE_KERNEL ", 16)==0 )
- {
- unsigned root_fs_ver = 0;
- token = strtok (line+16, search); // version
- sscanf (token, "%u", &root_fs_ver);
- printf("FIRMWARE_KERNEL_VERSION=%u\n",
- root_fs_ver);
- token = strtok(NULL, search); // alg
- printf("FIRMWARE_KERNEL_CS_ALG=%s\n", token);
-
- token = strtok(NULL, search); // comp hash
- printf("FIRMWARE_KERNEL_CS_COMP=%s\n", token);
-
- token = strtok(NULL, search); // uncomp hash
-
- printf("FIRMWARE_KERNEL_CS_UNCOMP=%s\n", token);
- token = strtok(NULL, search); // url hash
- printf( "FIRMWARE_KERNEL=%s\n", token) ;
-
- }
- else if( strncmp(line,"FIRMWARE_APPS ", 14)==0 )
- {
- unsigned root_fs_ver = 0;
- token = strtok (line+14, search); // version
- sscanf (token, "%u", &root_fs_ver);
- printf("FIRMWARE_APPS_VERSION=%u\n",
- root_fs_ver);
- token = strtok(NULL, search); // alg
- printf("FIRMWARE_APPS_CS_ALG=%s\n", token);
-
- token = strtok(NULL, search); // comp hash
- printf("FIRMWARE_APPS_CS_COMP=%s\n", token);
-
- token = strtok(NULL, search); // uncomp hash
-
- printf("FIRMWARE_APPS_CS_UNCOMP=%s\n", token);
- token = strtok(NULL, search); // url hash
- printf( "FIRMWARE_APPS=%s\n", token) ;
-
- }
-
- else if( strncmp(line,"DHCPV4 False ", 13)==0 )
- {
- FILE *f = fopen(atlas_netconfig_v4, "wt");
- char *ipv4_address;
- char *netmask;
- char *broadcast;
- char *ipv4_gw;
-
- if( f==NULL ) {
- atlas_log( ERROR, "Unable to create %s\n", atlas_netconfig_v4 );
- return 1;
- }
-
- // Statically configured probe.
-//DHCPV4 False IPV4ADDRESS 10.0.0.151 IPV4NETMASK 255.255.255.0 IPV4NETWORK 10.0.0.0 IPV4BROADCAST 10.0.0.255 IPV4GATEWAY 10.0.0.137
- // fprintf (f, "%s\n", line);
- token = strtok(line+13, search); //IPV4ADDRESS
- token = strtok(NULL, search); // <address>
- fprintf (f, "/sbin/ifconfig %s 0.0.0.0\n",
- str_device);
- fprintf (f, "/sbin/ifconfig %s:1 %s ",
- str_device, token);
- ipv4_address = token;
- token = strtok(NULL, search); // IPV4NETMASK
- token = strtok(NULL, search); //
- fprintf (f, "netmask %s ", token);
- netmask = token;
- token = strtok(NULL, search); // IPV4NETWORK
- token = strtok(NULL, search); //
- token = strtok(NULL, search); // IPV4BROADCAST
- token = strtok(NULL, search); //
- fprintf (f, "broadcast %s \n", token);
- broadcast = token;
- token = strtok(NULL, search); // IPV4GATEWAY
- token = strtok(NULL, search); //
- fprintf (f, "/sbin/route add default gw %s\n", token);
- ipv4_gw = token;
- ipv4_gw[(strlen(ipv4_gw) - 1)] = '\0';
-
- // put parts in the shell script to make network info file
-
- fprintf (f, "echo \"P_TO_C_NETWORK_UPDATE\" > %s \n", atlas_network_v4_info );
- fprintf (f, "echo \"IPV4_LOCAL_ADDR %s\" >> %s \n", ipv4_address, atlas_network_v4_info );
- fprintf (f, "echo \"IPV4_NETMASK %s\" >> %s \n", netmask, atlas_network_v4_info );
- fprintf (f, "echo \"IPV4_BROADCAST %s\" >> %s \n", broadcast, atlas_network_v4_info );
- fprintf (f, "echo \"IPV4_GW %s\" >> %s \n",ipv4_gw , atlas_network_v4_info );
- fprintf (f, "echo \"DHCP False \" >> %s \n", atlas_network_v4_info );
-
-
- // second file for static
- fprintf (f, "echo \"STATIC_IPV4_LOCAL_ADDR %s\" > %s \n", ipv4_address, atlas_network_v4_static_info );
- fprintf (f, "echo \"STATIC_IPV4_NETMASK %s\" >> %s \n", netmask, atlas_network_v4_static_info );
- fprintf (f, "echo \"STATIC_IPV4_BROADCAST %s\" >> %s \n", broadcast, atlas_network_v4_static_info );
- fprintf (f, "echo \"STATIC_IPV4_GW %s\" >> %s \n",ipv4_gw , atlas_network_v4_static_info );
- fprintf(f, "echo '"
- DBQ(static-inet-addresses) " : [ { "
- DBQ(inet-addr) ": " DBQ(%s) ", "
- DBQ(netmask) ": " DBQ(%s) ", "
- DBQ(interface) ": " DBQ(%s)
- " } ], "
- DBQ(static-inet-routes) " : [ { "
- DBQ(destination) ": " DBQ(0.0.0.0) ", "
- DBQ(netmask) ": " DBQ(0.0.0.0) ", "
- DBQ(next-hop) ": " DBQ(%s) ", "
- DBQ(interface) ": " DBQ(%s)
- " } ]' > %s\n",
- ipv4_address,
- netmask,
- str_device,
- ipv4_gw,
- str_device,
- atlas_network_v4_static_info_json);
- // ping the gateway
- fprintf (f, "ping -c 2 -q %s \n", ipv4_gw);
- fprintf (f, "IPV4_GW=%s; export IPV4_GW\n", ipv4_gw);
-
- fclose(f);
-
- do_rm_v4_static_info= 0;
- }
- //DHCPV6 False IPV6ADDRESS <address> IPV6PREFIXLEN <prefix> IPV6GATEWAY <gateway>]| [DHCPV6 True ]
- else if( strncmp(line,"DHCPV6 False ", 13)==0 )
- {
- FILE *f = fopen(atlas_netconfig_v6, "wt");
- char *ipv6_address;
- char *prefixlen;
- char *ipv6_gw;
-
- if( f==NULL ) {
- atlas_log( ERROR, "Unable to create %s\n", atlas_netconfig_v6 );
- return 1;
- }
-
- // Statically configured probe.
-
- //fprintf (f, "%s\n", line);
- token = strtok(line+13, search); //IPV6ADDRESS
- token = strtok(NULL, search); // <address>
- ipv6_address = token;
- token = strtok(NULL, search); // IPV6PREFIXLEN
- token = strtok(NULL, search); //
- prefixlen = token;
- fprintf (f, "/sbin/ifconfig %s 0.0.0.0\n",
- str_device);
- fprintf (f, "/sbin/ifconfig %s %s/%s\n",
- str_device, ipv6_address, prefixlen);
-
- token = strtok(NULL, search); // IPV6GATEWAY
- token = strtok(NULL, search); //
- ipv6_gw = token;
- ipv6_gw[(strlen(ipv6_gw) - 1)] = '\0';
- ///sbin/route -A inet6 add default gw fe80::13:0:0:1 dev eth0
- fprintf (f,
- "/sbin/route -A inet6 add default gw %s dev %s\n",
- ipv6_gw, str_device);
- // second file for static network info
- fprintf (f, "echo \"STATIC_IPV6_LOCAL_ADDR %s/%s\" > %s \n", ipv6_address, prefixlen, atlas_network_v6_static_info );
- fprintf (f, "echo \"STATIC_IPV6_GW %s\" >> %s \n",ipv6_gw , atlas_network_v6_static_info );
-
- fprintf(f, "echo '"
- DBQ(static-inet6-addresses) ": [ { "
- DBQ(inet6-addr) ": " DBQ(%s) ", "
- DBQ(prefix-length) ": %s, "
- DBQ(interface) ": " DBQ(%s) " } ], "
- DBQ(static-inet6-routes) ": [ { "
- DBQ(destination) ": " DBQ(::) ", "
- DBQ(prefix-length) " : 0, "
- DBQ(next-hop) ": " DBQ(%s) ", "
- DBQ(interface) ": " DBQ(%s) " } ]"
- "' > %s\n",
- ipv6_address, prefixlen, str_device,
- ipv6_gw, str_device,
- atlas_network_v6_static_info_json);
-
-
- fclose(f);
- do_rm_v6_static_info= 0;
- }
- else if( strncmp(line,"DNS_SERVERS ", 11)==0 )
- {
- FILE *f, *f1, *f2;
-
- f = fopen(atlas_resolv_conf, "wt");
- if( f==NULL ) {
- atlas_log(ERROR,
- "Unable to create %s\n",
- atlas_resolv_conf );
- return 1;
- }
-
- f1 = fopen(atlas_network_dns_static_info, "wt");
- if( f1==NULL ) {
- atlas_log(ERROR,
- "Unable to create %s\n",
- atlas_network_dns_static_info);
- fclose(f);
- return 1;
- }
- f2 = fopen(atlas_network_dns_static_info_json,
- "wt");
- if( f2==NULL ) {
- atlas_log(ERROR,
- "Unable to create %s\n",
- atlas_network_dns_static_info_json);
- fclose(f);
- fclose(f1);
- return 1;
- }
-
-
- // Statically configured probe.
- //DNS_SERVERS 8.8.8.8 194.109.6.66
- // fprintf (f, "%s\n", line);
- token = strtok(line+11, search_nl); //
- fprintf (f1, "STATIC_DNS");
- fprintf(f2, DBQ(static-dns) ": [ ");
-
- first= 1;
- while (token != NULL)
- {
- fprintf (f, "nameserver %s\n", token);
- fprintf (f1, " %s", token);
- fprintf(f2, "%s{ " DBQ(nameserver) ": "
- DBQ(%s) " }",
- first ? "" : ", ", token);
- token = strtok(NULL, search_nl);
- first= 0;
- }
- fprintf (f1, "\n");
- fprintf(f2, " ]\n");
-
- fclose(f);
- fclose(f1);
- fclose(f2);
-
- do_rm_dns_static_info= 0;
- }
- else if( strncmp(line,"FIRMWARE_KERNEL ", 16)==0 )
- {
- }
- bzero( line, ATLAS_BUF_SIZE );
- fgets( line, MAX_READ, read_from );
- l++;
- }
- if(do_rm_v4_static_info)
- {
- // delete the static configuration
- unlink(atlas_netconfig_v4);
- unlink(atlas_network_v4_static_info);
- unlink(atlas_network_v4_static_info_json);
- }
- if(do_rm_v6_static_info)
- {
- // delete the static configuration
- unlink(atlas_netconfig_v6);
- unlink(atlas_network_v6_static_info);
- unlink(atlas_network_v6_static_info_json);
- }
- if (do_rm_dns_static_info)
- {
- unlink(atlas_network_dns_static_info);
- unlink(atlas_network_dns_static_info_json);
- }
- }
- else if (strncmp(line,"WAIT\n",5) == 0 )
- {
- read_wait(read_from, "REG_WAIT_UNTIL", ATLAS_WAIT );
-
- }
- else {
- char *p = strchr(line,'\n');
- if( p!=NULL ) *p = '\0';
- atlas_log( ERROR, "OK expected, got \"%s\" instead\n", line );
- read_wait(read_from, "REG_WAIT_UNTIL", ATLAS_DEFAULT_WAIT); /* we got error the only action from probe is wait. so force it*/
- ret = 1;
- }
- return ret;
-}
-
-
-void atlas_log( int level UNUSED_PARAM, const char *msg UNUSED_PARAM, ... )
-{
-/*
- if( atlas_log_level<=level )
- {
- va_list arg;
- va_start ( arg, msg );
-
- FILE *lf = fopen( atlas_log_file, "at" );
- if( lf==NULL )
- return; // not much we can do
-
- fprintf( lf, "%d\t%d\t", (int)time(NULL), level );
- vfprintf( lf, msg, arg );
- fclose(lf);
-
- va_end( arg );
- }
-*/
-}
diff --git a/networking/atlasinit.h b/networking/atlasinit.h
deleted file mode 100644
index f7362a6..0000000
--- a/networking/atlasinit.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* RIPEAtlas
- * All the configurable variables - and some non configurables too
- * $Id: $
- */
-
-#ifndef _ATLASINIT_H
-#define _ATLASINIT_H
-
-#define ATLAS_BUF_SIZE 1024
-#define MAX_READ ATLAS_BUF_SIZE-2 /* should be enough to read controller keys */
-
-/*********************************************************************
- * Set these constants to your liking
- */
-
-extern const char atlas_log_file[];
-extern const int atlas_log_level;
-
-extern const char atlas_contr_known_hosts[];
-extern const char atlas_rereg_timestamp[];
-
-extern const int max_lines; /* maximum lines we'll process */
-extern const int min_rereg_time; /* 12h */
-extern const int max_rereg_time; /* 28d */
-extern const int default_rereg_time; /* 7d */
-
-/*********************************************************************/
-
-enum { ALL, DEBUG, INFO, WARN, ERROR } error_level;
-
-void atlas_log( int level, const char *msg, ... );
-
-#endif
diff --git a/networking/rptaddr6.c b/networking/rptaddr6.c
deleted file mode 100644
index 9c60425..0000000
--- a/networking/rptaddr6.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * rptaddr6.c
- * Copyright (c) 2013 RIPE NCC <atlas@ripe.net>
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <net/route.h>
-#include <inet_common.h>
-#include "../eperd/eperd.h"
-
-#include "libbb.h"
-
-#define IF_INET6_FILE "/proc/net/if_inet6"
-#define IPV6_ROUTE_FILE "/proc/net/ipv6_route"
-#define SUFFIX ".new"
-
-#define SAFE_PREFIX_O ATLAS_DATA_OUT
-#define SAFE_PREFIX_N ATLAS_DATA_NEW
-
-#define OPT_STRING "A:O:c:"
-
-#define DBQ(str) "\"" #str "\""
-#define JS(key, val) fprintf(fh, "\"" #key"\" : \"%s\" , ", val);
-#define JS1(key, fmt, val) fprintf(fh, "\"" #key"\" : "#fmt" , ", val);
-
-#ifndef IPV6_MASK
-#define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE)
-#endif
-
-#define IPV6_ADDR_LOOPBACK 0x0010U
-#define IPV6_ADDR_LINKLOCAL 0x0020U
-#define IPV6_ADDR_SITELOCAL 0x0040U
-
-#define IPV6_ADDR_COMPATv4 0x0080U
-
-#define IPV6_ADDR_SCOPE_MASK 0x00f0U
-
-enum {
- OPT_a = (1 << 0),
-};
-
-static int setup_ipv6_rpt(char *cache_name, int *need_report);
-static int rpt_ipv6(char *cache_name, char *out_name, char *opt_atlas, int opt_append);
-static void report(const char *fmt, ...);
-static void report_err(const char *fmt, ...);
-
-int rptaddr6_main(int argc, char *argv[])
-{
- int r, need_report;
- unsigned opt;
- char *opt_atlas;
- char *cache_name; /* temp file in an intermediate format */
- char *out_name; /* output file in json: timestamp opt_atlas */
- int opt_append;
-
- opt_atlas= NULL;
- out_name = NULL;
- cache_name = NULL;
- opt_atlas = NULL;
- opt_complementary= NULL;
- opt_append = FALSE;
-
- opt= getopt32(argv, OPT_STRING, &opt_atlas, &out_name, &cache_name);
-
- if (out_name && !validate_filename(out_name, SAFE_PREFIX_O))
- {
- crondlog(LVL8 "insecure file '%s' : allowed '%s'", out_name,
- SAFE_PREFIX_O);
- return 1;
- }
- if (cache_name && !validate_filename(cache_name, SAFE_PREFIX_N))
- {
- crondlog(LVL8 "insecure file '%s' allowed %s", cache_name,
- SAFE_PREFIX_N);
- return 1;
- }
-
- if (!cache_name) {
- crondlog(LVL8 "missing requried option, -c <cache_file>");
- return 1;
- }
-
- if (opt & OPT_a)
- opt_append = TRUE;
-
- r= setup_ipv6_rpt(cache_name, &need_report);
- if (r != 0)
- return r;
- if (need_report)
- {
- r = rpt_ipv6(cache_name, out_name, opt_atlas, opt_append);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-static int setup_ipv6_rpt(char *cache_name, int *need_report)
-{
- int i, r, n;
- char *cp, *cp1;
- char filename[80];
- char dst6in[INET6_ADDRSTRLEN];
- char nh6in[INET6_ADDRSTRLEN]; /* next hop */
- char *dst6out = NULL;
- char *nh6out = NULL;
- char dst6p[8][5];
- char nh6p[8][5];
- char iface[16], flags[16];
- char Scope[32];
- int scope, dad_status, if_idx;
- int iflags, metric, refcnt, use, prefix_len, slen;
- struct sockaddr_in6 sdst6, snh6;
-
- char buf1[1024];
- char buf2[1024];
- FILE *in_file, *out_file, *cache_file;
-
- *need_report= 0;
-
- if (strlen(cache_name) + strlen(SUFFIX) + 1 > sizeof(filename))
- {
- report("cache name '%s' too long", cache_name);
- return 1;
- }
-
- strlcpy(filename, cache_name, sizeof(filename));
- strlcat(filename, SUFFIX, sizeof(filename));
-
- out_file= fopen(filename, "w");
- if (out_file == NULL)
- {
- report_err("unable to create '%s'", filename);
- return 1;
- }
-
- /* Copy IF_INET6_FILE */
- in_file= fopen(IF_INET6_FILE, "r");
- if (in_file == NULL)
- {
- report_err("unable to open '%s'", IF_INET6_FILE);
- fclose(out_file);
- return 1;
- }
- n = 0;
- while ((r = fscanf(in_file, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
- dst6p[0], dst6p[1], dst6p[2]
- , dst6p[3], dst6p[4], dst6p[5]
- , dst6p[6], dst6p[7], &if_idx, &prefix_len
- , &scope, &dad_status, iface)) != EOF) {
-
- snprintf(dst6in, sizeof(dst6in), "%s:%s:%s:%s:%s:%s:%s:%s",
- dst6p[0], dst6p[1], dst6p[2], dst6p[3],
- dst6p[4], dst6p[5], dst6p[6], dst6p[7]);
-
- inet_pton(AF_INET6, dst6in, (struct sockaddr *) &sdst6.sin6_addr);
- sdst6.sin6_family = AF_INET6;
- dst6out = INET6_rresolve((struct sockaddr_in6 *) &sdst6, 0x0fff);
-
- switch (scope & IPV6_ADDR_SCOPE_MASK) {
- case 0:
- snprintf(Scope, sizeof(Scope), "Global");
- break;
- case IPV6_ADDR_LINKLOCAL:
- snprintf(Scope, sizeof(Scope), "Link");
- break;
- case IPV6_ADDR_SITELOCAL:
- snprintf(Scope, sizeof(Scope), "Site");
- break;
- case IPV6_ADDR_COMPATv4:
- snprintf(Scope, sizeof(Scope), "Compat");
- break;
- case IPV6_ADDR_LOOPBACK:
- snprintf(Scope, sizeof(Scope), "Host");
- break;
- default:
- snprintf(Scope, sizeof(Scope), "Unknown %d", scope);
- }
- r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(inet6 addr) " : "
- DBQ(%s) ", " DBQ(prefix length) " : %d,"
- DBQ(scope) " : " DBQ(%s) ", " DBQ(interface)
- " : " DBQ(%s) "}",
- n ? "" : "\"inet6 addresses\" : [", n ? ", " : ""
- , dst6out, prefix_len, Scope, iface);
-
- /* printf("%s\n", buf2); */
-
- if(dst6out) {
- free(dst6out);
- dst6out=NULL;
- }
- n++;
- if (fwrite(buf2, 1, r, out_file) != r)
- {
- report_err("error writing to '%s'", filename);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
-
- if (ferror(in_file))
- {
- report_err("error reading from '%s'", IF_INET6_FILE);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
- }
- if ( n > 0 ) {
- r = snprintf(buf2, 2, "]");
- }
- if (fwrite(buf2, 1, r, out_file) != r)
- {
- report_err("error writing to '%s'", filename);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
-
- fclose(in_file);
-
- /* Copy IPV6_ROUTE_FILE */
- in_file= fopen(IPV6_ROUTE_FILE, "r");
- if (in_file == NULL)
- {
- report_err("unable to open '%s'", IPV6_ROUTE_FILE);
- fclose(out_file);
- return 1;
- }
-
- n = 0;
- while ((r = fscanf (in_file, "%4s%4s%4s%4s%4s%4s%4s%4s%x%*s%x%4s%4s%4s%4s%4s%4s%4s%4s%x%x%x%x%s\n",
- dst6p[0], dst6p[1], dst6p[2], dst6p[3], dst6p[4],
- dst6p[5], dst6p[6], dst6p[7], &prefix_len, &slen,
- nh6p[0], nh6p[1], nh6p[2], nh6p[3], nh6p[4],
- nh6p[5], nh6p[6], nh6p[7], &metric, &use, &refcnt, &iflags, iface)) != EOF) {
-
- if (r != 23) {
- if ((r < 0) && feof(in_file)) { /* EOF with no (nonspace) chars read. */
- break;
- }
- report_err("reading '%s'", IF_INET6_FILE);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
-
- /* skip some the stuff we don't want to report */
- if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */
- continue;
- }
- if ((iflags & RTF_ADDRCONF) && (iflags & RTF_CACHE)) { /* Skip interfaces that are down. */
- continue;
- }
-
- if ( strncmp (dst6p[0], "ff02", strlen("ff02")) == 0 ) {
- continue;
- }
- if ( strncmp (dst6p[0], "ff00", strlen("ff00")) == 0 ) {
- continue;
- }
-
- snprintf(dst6in, sizeof(dst6in), "%s:%s:%s:%s:%s:%s:%s:%s",
- dst6p[0], dst6p[1], dst6p[2], dst6p[3],
- dst6p[4], dst6p[5], dst6p[6], dst6p[7]);
-
- snprintf(nh6in, sizeof(nh6in), "%s:%s:%s:%s:%s:%s:%s:%s",
- nh6p[0], nh6p[1], nh6p[2], nh6p[3],
- nh6p[4], nh6p[5], nh6p[6], nh6p[7]);
-
-
- set_flags(flags, (iflags & IPV6_MASK));
- inet_pton(AF_INET6, dst6in, (struct sockaddr *) &sdst6.sin6_addr);
- sdst6.sin6_family = AF_INET6;
- dst6out = INET6_rresolve((struct sockaddr_in6 *) &sdst6, 0x0fff);
-
- inet_pton(AF_INET6, nh6in, (struct sockaddr *) &snh6.sin6_addr);
- snh6.sin6_family = AF_INET6;
- nh6out = INET6_rresolve((struct sockaddr_in6 *) &snh6, 0x0fff);
-
-
- r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(destination) " : "
- DBQ(%s) ", " DBQ(prefix length) " : %d,"
- DBQ(next hop) " : " DBQ(%s) ", " DBQ(flags)
- " : " DBQ(%s) ", " DBQ(metric) " : %d , "
- DBQ(interface) " : " DBQ(%s) "}",
- n ? "" : ", \"inet6 routes\" : [", n ? ", " : ""
- , dst6out, prefix_len, nh6out, flags, metric
- , iface);
-
- /*
- r = snprintf(buf2, sizeof(buf2), "%s %s{" DBQ(destination) " : "
- DBQ(%s) ", " DBQ(prefix length) " : %d,"
- DBQ(next hop) " : " DBQ(%s) ", " DBQ(flags)
- " : " DBQ(%s) ", " DBQ(metric) " : %d , "
- DBQ(interface) " : " DBQ(%s) "}",
- n ? " " : '"inet6 routes" ['
- , n ? ", " : ""
- , dst6out, prefix_len, nh6out, flags, metric
- , iface);
- */
-
- /* printf("%s\n", buf2); */
-
- if(dst6out) {
- free(dst6out);
- dst6out=NULL;
- }
- if(nh6out) {
- free(nh6out);
- nh6out=NULL;
- }
-
- if (fwrite(buf2, 1, r, out_file) != r)
- {
- report_err("error writing to '%s'", filename);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
- n++;
- }
- if ( n > 0 ) {
- r = snprintf(buf2, 2, "]");
- }
- if (fwrite(buf2, 1, r, out_file) != r)
- {
- report_err("error writing to '%s'", filename);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
-
-
- if (ferror(in_file))
- {
- report_err("error reading from '%s'", IPV6_ROUTE_FILE);
- fclose(in_file);
- fclose(out_file);
- return 1;
- }
- fclose(in_file);
-
- /* Now check if the new file is different from the cache one */
- fclose(out_file);
- cache_file= fopen(cache_name, "r");
- if (cache_file == NULL)
- {
- /* Assume that any kind of error here calls for reporting */
- *need_report= 1;
- }
-
- if (cache_file)
- {
- in_file= fopen(filename, "r");
- if (in_file == NULL)
- {
- report_err("unable to open '%s'", filename);
- fclose(cache_file);
- return 1;
- }
-
- /* Compare them */
- while (r= fread(buf1, 1, sizeof(buf1), cache_file), r > 0)
- {
- if (fread(buf2, 1, sizeof(buf2), in_file) != r)
- {
- /* Ignore errors, just report */
- *need_report= 1;
- break;
- }
-
- if (memcmp(buf1, buf2, r) != 0)
- {
- /* Something changed, report */
- *need_report= 1;
- break;
- }
- }
-
- /* Maybe something got added */
- if (!*need_report)
- {
- if (fread(buf2, 1, sizeof(buf2), in_file) != 0)
- {
- *need_report= 1;
- }
- }
- fclose(cache_file);
- fclose(in_file);
- }
-
- if (*need_report)
- {
- if (rename(filename, cache_name) == -1)
- {
- report_err("renaming '%s' to '%s' failed",
- filename, cache_name);
- return 1;
- }
- }
- else
- {
- if (unlink(filename) == -1)
- {
- report_err("unlinking '%s' failed",
- filename);
- }
- }
-
- return 0;
-}
-
-
-static int rpt_ipv6(char *cache_name, char *out_name, char *opt_atlas, int opt_append)
-{
- FILE *file;
- FILE *fh;
- char *cp;
- char buf[256];
- struct timeval now;
-
- file= fopen(cache_name, "r");
- if (!file)
- {
- report_err("unable to open cache file '%s'", cache_name);
- return 1;
- }
-
- if (out_name) {
- if(opt_append)
- fh= fopen(out_name, "w");
- else
- fh= fopen(out_name, "w");
-
- if (!fh)
- crondlog(DIE9 "unable to append to '%s'", out_name);
- }
- else
- fh = stdout;
-
- fprintf(fh, "RESULT { ");
- if(opt_atlas)
- {
- JS(id, opt_atlas);
- }
- gettimeofday(&now, NULL);
- JS1(time, %ld, now.tv_sec);
-
- /* Copy all lines */
- while (fgets(buf, sizeof(buf), file) != NULL)
- {
- fputs(buf, fh);
- }
- fprintf(fh, "}\n");
- fclose(file);
- fclose(fh);
-
- return 0;
-}
-
-static void report(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-
- fprintf(stderr, "rptaddr6: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
-
- va_end(ap);
-}
-
-static void report_err(const char *fmt, ...)
-{
- int t_errno;
- va_list ap;
-
- t_errno= errno;
-
- va_start(ap, fmt);
-
- fprintf(stderr, "rptaddr6: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, ": %s\n", strerror(t_errno));
-
- va_end(ap);
-}
diff --git a/networking/rptaddrs.c b/networking/rptaddrs.c
index 3285d36..33d20cf 100644
--- a/networking/rptaddrs.c
+++ b/networking/rptaddrs.c
@@ -285,6 +285,14 @@ static int setup_dhcpv4(FILE *of)
in_file= fopen(NETWORK_INFO, "r");
if (in_file == NULL)
{
+ if (errno == ENOENT)
+ {
+ /* Probe is configure for DHCP but didn't get a
+ * DHCP lease.
+ */
+ fprintf(of, ", " DBQ(inet-dhcp) ": true");
+ return 0;
+ }
report_err("unable to open '%s'", NETWORK_INFO);
return -1;
}