aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2015-05-15 10:25:21 +0200
committerBjørn Mork <bjorn@mork.no>2015-05-15 10:25:21 +0200
commitb8c5c3b44362778c099531f7a905c56a0423bcef (patch)
treee9ccaff5d19f39e7bc58734e1b5babf4025a3a9c
parentb1b227fa5e00d08af047ab9a012211b66c6b0f13 (diff)
ripe-atlas-fw: imported version 46504650
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--.config4
-rw-r--r--checksum4
-rw-r--r--eperd/eooqd.c5
-rw-r--r--eperd/evtdig.c17
-rw-r--r--eperd/httpget.c21
-rw-r--r--eperd/ping.c350
-rw-r--r--eperd/readresolv.c39
-rw-r--r--eperd/readresolv.h2
-rw-r--r--eperd/sslgetcert.c11
-rw-r--r--eperd/tcputil.c44
-rw-r--r--eperd/tcputil.h5
-rw-r--r--eperd/traceroute.c674
-rw-r--r--include/applets.h2
-rw-r--r--include/libbb.h2
-rw-r--r--include/usage.h12
-rw-r--r--libbb/Kbuild2
-rw-r--r--libbb/atlas_timesync.c19
-rw-r--r--libbb/bind_interface.c42
-rw-r--r--networking/Config.in6
-rw-r--r--networking/Kbuild2
-rw-r--r--networking/atlasinit.c740
-rw-r--r--networking/rptaddrs.c775
-rw-r--r--networking/rptra6.c2
-rw-r--r--shell/hush.c10
24 files changed, 2258 insertions, 532 deletions
diff --git a/.config b/.config
index fe8c41e..f6026bd 100644
--- a/.config
+++ b/.config
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Busybox version: 1.13.3
-# Mon Mar 10 17:14:26 2014
+# Wed May 7 07:15:57 2014
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -711,7 +711,7 @@ CONFIG_FEATURE_FANCY_PING=y
CONFIG_PSCAN=y
CONFIG_ROUTE=y
CONFIG_RPTRA6=y
-CONFIG_RPTADDR6=y
+CONFIG_RPTADDRS=y
CONFIG_RXTXRPT=y
CONFIG_SLATTACH=y
CONFIG_SSLGETCERT=y
diff --git a/checksum b/checksum
index bcff836..cd6d912 100644
--- a/checksum
+++ b/checksum
@@ -1,2 +1,2 @@
-9220584710f5cb827a35a20b139231c774d60bc1e66706cc42c6808a34a28b34 ripe-atlas-fw-4570.tar.gz
-5fa4008d6321d66ed15235dd51bef6fbee1c455dccdf01c1b9a92db979a82fdc307dd2f11cc9f79de2adf467638954180c4d5b9ad9e30501f699af7691079bbc ripe-atlas-fw-4570.tar.gz
+6b015256e73151f92c700c31c4551c24fef023e57c74316fa35d024f013b1737 ripe-atlas-fw-4610.tar.gz
+8d22f3f0e332df7271c893ea599975939e29fda1e0a9f001dc7b50dd2ffc835c43c2859042ba835edce312222e830e38c6c6cc417b038e234d3f14942120dd39 ripe-atlas-fw-4610.tar.gz
diff --git a/eperd/eooqd.c b/eperd/eooqd.c
index 7e071c0..41efa1b 100644
--- a/eperd/eooqd.c
+++ b/eperd/eooqd.c
@@ -616,7 +616,10 @@ static const char *get_session_id(void)
cp= strchr(session_id, '\n');
if (cp)
*cp= '\0';
- return session_id;
+ cp= strrchr(session_id, ' ');
+ if (!cp)
+ return NULL;
+ return cp+1;
}
static void skip_space(char *cp, char **ncpp)
diff --git a/eperd/evtdig.c b/eperd/evtdig.c
index b3813de..e0a8ae5 100644
--- a/eperd/evtdig.c
+++ b/eperd/evtdig.c
@@ -712,7 +712,7 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet)
dns->aa = 0; //Not Authoritative
dns->tc = 0; //This message is not truncated
dns->rd = 0; //Recursion not Desired
- dns->ra = 1; //Recursion not available! hey we dont have it (lol)
+ dns->ra = 0; //Recursion not available! hey we dont have it (lol)
dns->z = 0;
dns->ad = 0;
dns->cd = 0;
@@ -1895,7 +1895,8 @@ void tdig_start (struct query_state *qry)
interval.tv_sec = CONN_TO;
interval.tv_usec= 0;
tu_connect_to_name (&qry->tu_env, qry->server_name, port_as_char,
- &interval, &hints, tcp_timeout_callback, tcp_reporterr,
+ &interval, &hints, NULL,
+ tcp_timeout_callback, tcp_reporterr,
tcp_dnscount, tcp_beforeconnect,
tcp_connected, tcp_readcb, tcp_writecb);
@@ -2194,7 +2195,9 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result)
int flagAnswer = 0;
int data_len;
int write_out = FALSE;
- u_int32_t fw;
+
+ int fw = get_atlas_fw_version();
+ int lts = get_timesync();
if(! qry->result.size){
buf_init(&qry->result, -1);
@@ -2206,19 +2209,21 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result)
JS(id, qry->str_Atlas);
}
- fw = get_atlas_fw_version();
- JU(fw, fw);
-
+ JD(fw, fw);
if (qry->opt_rset){
JS1(time, %ld, qry->xmit_time.tv_sec);
+ JD(lts,lts);
AS("\"resultset\" : [ {");
}
+
}
else if(qry->opt_rset) {
AS (",{");
}
JS1(time, %ld, qry->xmit_time.tv_sec);
+ JD(lts,lts);
+
if ( qry->opt_resolv_conf ) {
JD (subid, (qry->resolv_i+1));
JD (submax, qry->base->resolv_max);
diff --git a/eperd/httpget.c b/eperd/httpget.c
index d0d3e4c..4b22bca 100644
--- a/eperd/httpget.c
+++ b/eperd/httpget.c
@@ -91,6 +91,7 @@ struct hgstate
int etim;
size_t read_limit;
unsigned timeout;
+ char *infname;
/* State */
char busy;
@@ -368,7 +369,7 @@ static void *httpget_init(int __attribute((unused)) argc, char *argv[],
char *url, *check;
char *post_file, *output_file, *post_footer, *post_header,
*A_arg, *store_headers, *store_body, *read_limit_str,
- *timeout_str;
+ *timeout_str, *infname;
const char *user_agent;
char *host, *port, *hostport, *path;
struct hgstate *state;
@@ -390,6 +391,7 @@ static void *httpget_init(int __attribute((unused)) argc, char *argv[],
read_limit_str= NULL;
timeout_str= NULL;
A_arg= NULL;
+ infname= NULL;
only_v4= 0;
only_v6= 0;
do_etim= 0;
@@ -406,7 +408,7 @@ static void *httpget_init(int __attribute((unused)) argc, char *argv[],
/* Allow us to be called directly by another program in busybox */
optind= 0;
- while (c= getopt_long(argc, argv, "01aA:cO:46", longopts, NULL), c != -1)
+ while (c= getopt_long(argc, argv, "01aA:cI:O:46", longopts, NULL), c != -1)
{
switch(c)
{
@@ -455,6 +457,9 @@ static void *httpget_init(int __attribute((unused)) argc, char *argv[],
case 'h': /* --post-header */
post_header= optarg;
break;
+ case 'I':
+ infname= optarg;
+ break;
case 'O':
output_file= optarg;
break;
@@ -622,6 +627,7 @@ static void *httpget_init(int __attribute((unused)) argc, char *argv[],
state->max_body= max_body;
state->read_limit= read_limit;
state->timeout= timeout;
+ state->infname= infname;
state->only_v4= 2;
@@ -701,8 +707,10 @@ static void report(struct hgstate *state)
{
fprintf(fh, DBQ(id) ":" DBQ(%s) ", "
DBQ(fw) ":%d, "
+ DBQ(lts) ":%d, "
DBQ(time) ":%ld, ",
state->atlas, get_atlas_fw_version(),
+ get_timesync(),
state->gstart);
}
fprintf(fh, DBQ(result) ":[ ");
@@ -1822,6 +1830,13 @@ static void reporterr(struct tu_env *env, enum tu_err cause,
err_reading(state);
break;
+ case TU_SOCKET_ERR:
+ snprintf(line, sizeof(line),
+ "{ " DBQ(sockerr) ":" DBQ(%s) ", ", str);
+ add_str(state, line);
+ report(state);
+ break;
+
case TU_CONNECT_ERR:
snprintf(line, sizeof(line),
DBQ(err) ":" DBQ(connect: %s) ", ", str);
@@ -1890,7 +1905,7 @@ static void httpget_start(void *state)
interval.tv_sec= hgstate->timeout / 1000;
interval.tv_usec= (hgstate->timeout % 1000) * 1000;
tu_connect_to_name(&hgstate->tu_env, hgstate->host, hgstate->port,
- &interval, &hints, timeout_callback,
+ &interval, &hints, hgstate->infname, timeout_callback,
reporterr, dnscount, beforeconnect,
connected, readcb, writecb);
}
diff --git a/eperd/ping.c b/eperd/ping.c
index 16aa8fe..4d17317 100644
--- a/eperd/ping.c
+++ b/eperd/ping.c
@@ -26,7 +26,7 @@
#define DBQ(str) "\"" #str "\""
-#define PING_OPT_STRING ("!46rc:s:A:O:")
+#define PING_OPT_STRING ("!46rc:s:A:O:i:I:")
enum
{
@@ -71,25 +71,13 @@ struct pingbase
{
struct event_base *event_base;
- evutil_socket_t rawfd4; /* Raw socket used to ping hosts (IPv4)
- */
- evutil_socket_t rawfd6; /* Raw socket used to ping hosts (IPv6)
- */
-
pid_t pid; /* Identifier to send with each ICMP
* Request */
- struct timeval tv_interval; /* Ping interval between two subsequent
- * pings */
-
/* A list of hosts to ping. */
struct pingstate **table;
int tabsiz;
- struct event event4; /* Used to detect read events on raw
- * socket */
- struct event event6; /* Used to detect read events on raw
- * socket */
void (*done)(void *state); /* Called when a ping is done */
u_char packet [MAX_DATA_SIZE];
@@ -100,9 +88,11 @@ struct pingstate
/* Parameters */
char *atlas;
char *hostname;
+ char *interface;
int pingcount;
char *out_filename;
char delay_name_res;
+ unsigned interval;
/* State */
struct sockaddr_in6 sin6;
@@ -110,6 +100,7 @@ struct pingstate
struct sockaddr_in6 loc_sin6;
socklen_t loc_socklen;
int busy;
+ int socket;
char got_reply;
char first;
char no_dst;
@@ -117,6 +108,9 @@ struct pingstate
unsigned size;
unsigned psize;
+ struct event event; /* Used to detect read events on raw
+ * socket */
+
char *result;
size_t reslen;
size_t resmax;
@@ -186,19 +180,6 @@ static void add_str(struct pingstate *state, const char *str)
//printf("add_str: result = '%s'\n", state->result);
}
-static int get_timesync(void)
-{
- FILE *fh;
- int lastsync;
-
- fh= fopen(ATLAS_TIMESYNC_FILE, "r");
- if (!fh)
- return -1;
- fscanf(fh, "%d", &lastsync);
- fclose(fh);
- return time(NULL)-lastsync;
-}
-
static void report(struct pingstate *state)
{
FILE *fh;
@@ -259,13 +240,23 @@ static void report(struct pingstate *state)
#endif /* DO_PSIZE */
fprintf(fh, ", \"result\": [ %s ] }\n", state->result);
+
free(state->result);
state->result= NULL;
- state->busy= 0;
-
if (state->out_filename)
fclose(fh);
+
+ /* Kill the event and close socket */
+ event_del(&state->event);
+ if (state->socket != -1)
+ {
+ close(state->socket);
+ state->socket= -1;
+ }
+
+ state->busy= 0;
+
}
static void ping_cb(int result, int bytes, int psize,
@@ -558,8 +549,9 @@ static void fmticmp6(u_char *buffer, size_t *sizep,
static void ping_xmit(struct pingstate *host)
{
struct pingbase *base = host->base;
+ struct timeval tv_interval;
- int nsent, fd4, fd6, t_errno, r;
+ int nsent;
if (host->sentpkts >= host->maxpkts)
{
@@ -587,27 +579,14 @@ static void ping_xmit(struct pingstate *host)
fmticmp6(base->packet, &host->cursize, host->seq, host->index,
base->pid);
- fd6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- if (fd6 != -1)
- {
- r= connect(fd6, (struct sockaddr *)&host->sin6,
- host->socklen);
- if (r == 0)
- {
- host->loc_socklen=
- sizeof(host->loc_sin6);
- getsockname(fd6, &host->loc_sin6,
- &host->loc_socklen);
- }
- }
+ host->loc_socklen= sizeof(host->loc_sin6);
+ getsockname(host->socket, &host->loc_sin6, &host->loc_socklen);
- nsent = sendto(fd6, base->packet, host->cursize+ICMP6_HDRSIZE,
+ nsent = sendto(host->socket, base->packet,
+ host->cursize+ICMP6_HDRSIZE,
MSG_DONTWAIT, (struct sockaddr *)&host->sin6,
host->socklen);
- t_errno= errno;
- close(fd6);
- errno= t_errno;
}
else
{
@@ -615,28 +594,13 @@ static void ping_xmit(struct pingstate *host)
fmticmp4(base->packet, &host->cursize, host->seq, host->index,
base->pid);
- fd4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (fd4 != -1)
- {
- r= connect(fd4, (struct sockaddr *)&host->sin6,
- host->socklen);
- if (r == 0)
- {
- host->loc_socklen=
- sizeof(host->loc_sin6);
- getsockname(fd4, &host->loc_sin6,
- &host->loc_socklen);
- }
- }
+ host->loc_socklen= sizeof(host->loc_sin6);
+ getsockname(host->socket, &host->loc_sin6, &host->loc_socklen);
-
- nsent = sendto(fd4, base->packet, host->cursize+ICMP_MINLEN,
+ nsent = sendto(host->socket, base->packet,
+ host->cursize+ICMP_MINLEN,
MSG_DONTWAIT, (struct sockaddr *)&host->sin6,
host->socklen);
-
- t_errno= errno;
- close(fd4);
- errno= t_errno;
}
if (nsent > 0)
@@ -660,7 +624,8 @@ static void ping_xmit(struct pingstate *host)
/* Add the timer to handle no reply condition in the given timeout */
- evtimer_add(&host->ping_timer, &host->base->tv_interval);
+ msecstotv(host->interval, &tv_interval);
+ evtimer_add(&host->ping_timer, &tv_interval);
}
@@ -673,9 +638,7 @@ static void noreply_callback(int __attribute((unused)) unused, const short __att
{
ping_cb(PING_ERR_TIMEOUT, host->cursize, -1,
(struct sockaddr *)&host->sin6, host->socklen,
- NULL, 0,
- host->seq, -1, &host->base->tv_interval,
- host);
+ NULL, 0, host->seq, -1, NULL, host);
/* Update the sequence number for the next run */
host->seq = (host->seq + 1) % 256;
@@ -698,29 +661,32 @@ static void noreply_callback(int __attribute((unused)) unused, const short __att
static void ready_callback4 (int __attribute((unused)) unused,
const short __attribute((unused)) event, void * arg)
{
- struct pingbase *base = arg;
-
+ struct pingstate *state;
+ struct pingbase *base;
int nrecv, isDup;
- struct sockaddr_in remote; /* responding internet address */
+ struct sockaddr_in remote; /* responding internet address */
socklen_t slen = sizeof(struct sockaddr);
struct sockaddr_in *sin4p;
struct sockaddr_in loc_sin4;
-
- /* Pointer to relevant portions of the packet (IP, ICMP and user data) */
- struct ip * ip = (struct ip *) base->packet;
+ struct ip * ip;
struct icmphdr * icmp;
- struct evdata * data = (struct evdata *) (base->packet + IPHDR + ICMP_MINLEN);
+ struct evdata * data;
int hlen = 0;
-
struct timeval now;
- struct pingstate * host;
+ state= arg;
+ base = state->base;
+
+ /* Pointer to relevant portions of the packet (IP, ICMP and user
+ * data) */
+ ip = (struct ip *) base->packet;
+ data = (struct evdata *) (base->packet + IPHDR + ICMP_MINLEN);
/* Time the packet has been received */
gettimeofday(&now, NULL);
// printf("ready_callback4: before recvfrom\n");
/* Receive data from the network */
- nrecv = recvfrom(base->rawfd4, base->packet, sizeof(base->packet), MSG_DONTWAIT, (struct sockaddr *) &remote, &slen);
+ nrecv = recvfrom(state->socket, base->packet, sizeof(base->packet), MSG_DONTWAIT, (struct sockaddr *) &remote, &slen);
if (nrecv < 0)
{
goto done;
@@ -766,7 +732,8 @@ printf("ready_callback4: too short\n");
}
/* Get the pointer to the host descriptor in our internal table */
- host= base->table[data->index];
+ if (state != base->table[data->index])
+ goto done; /* Not for us */
/* Check for Destination Host Unreachable */
if (icmp->type == ICMP_ECHO)
@@ -786,31 +753,31 @@ printf("ready_callback4: too short\n");
memset(sin4p, '\0', sizeof(*sin4p));
sin4p->sin_family= AF_INET;
sin4p->sin_addr= ip->ip_dst;
- host->rcvd_ttl= ip->ip_ttl;
+ state->rcvd_ttl= ip->ip_ttl;
/* Report everything with the wrong sequence number as a dup.
* This is not quite right, it could be a late packet. Do we
* care?
*/
- isDup= (ntohs(icmp->un.echo.sequence) != host->seq);
+ isDup= (ntohs(icmp->un.echo.sequence) != state->seq);
ping_cb(isDup ? PING_ERR_DUP : PING_ERR_NONE,
nrecv - IPHDR - ICMP_MINLEN, nrecv,
- (struct sockaddr *)&host->sin6, host->socklen,
+ (struct sockaddr *)&state->sin6, state->socklen,
(struct sockaddr *)&loc_sin4, sizeof(loc_sin4),
ntohs(icmp->un.echo.sequence), ip->ip_ttl, &elapsed,
- host);
+ state);
/* Update the sequence number for the next run */
- host->seq = (host->seq + 1) % 256;
+ state->seq = (state->seq + 1) % 256;
if (!isDup)
- host->got_reply= 1;
+ state->got_reply= 1;
}
else
{
printf("ready_callback4: not an echo reply\n");
/* Handle this condition exactly as the request has expired */
- noreply_callback (-1, -1, host);
+ noreply_callback (-1, -1, state);
}
done:
@@ -831,18 +798,16 @@ done:
static void ready_callback6 (int __attribute((unused)) unused,
const short __attribute((unused)) event, void * arg)
{
- struct pingbase *base = arg;
+ struct pingbase *base;
+ struct pingstate *state;
int nrecv, isDup;
struct sockaddr_in remote; /* responding internet address */
- /* Pointer to relevant portions of the packet (IP, ICMP and user data) */
- struct icmp6_hdr * icmp = (struct icmp6_hdr *) base->packet;
- struct evdata * data = (struct evdata *) (base->packet +
- offsetof(struct icmp6_hdr, icmp6_data16[2]));
+ struct icmp6_hdr *icmp;
+ struct evdata * data;
struct timeval now;
- struct pingstate * host;
struct cmsghdr *cmsgptr;
struct sockaddr_in6 *sin6p;
struct msghdr msg;
@@ -850,6 +815,15 @@ static void ready_callback6 (int __attribute((unused)) unused,
struct iovec iov[1];
char cmsgbuf[256];
+ state= arg;
+ base = state->base;
+
+ /* Pointer to relevant portions of the packet (IP, ICMP and user
+ * data) */
+ icmp = (struct icmp6_hdr *) base->packet;
+ data = (struct evdata *) (base->packet +
+ offsetof(struct icmp6_hdr, icmp6_data16[2]));
+
/* Time the packet has been received */
gettimeofday(&now, NULL);
@@ -864,7 +838,7 @@ static void ready_callback6 (int __attribute((unused)) unused,
msg.msg_flags= 0; /* Not really needed */
/* Receive data from the network */
- nrecv= recvmsg(base->rawfd6, &msg, MSG_DONTWAIT);
+ nrecv= recvmsg(state->socket, &msg, MSG_DONTWAIT);
if (nrecv < 0)
{
goto done;
@@ -885,7 +859,8 @@ static void ready_callback6 (int __attribute((unused)) unused,
}
/* Get the pointer to the host descriptor in our internal table */
- host= base->table[data->index];
+ if (state != base->table[data->index])
+ goto done; /* Not for us */
/* Check for Destination Host Unreachable */
if (icmp->icmp6_type == ICMP6_ECHO_REPLY)
@@ -914,7 +889,7 @@ static void ready_callback6 (int __attribute((unused)) unused,
if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
cmsgptr->cmsg_type == IPV6_HOPLIMIT)
{
- host->rcvd_ttl= *(int *)CMSG_DATA(cmsgptr);
+ state->rcvd_ttl= *(int *)CMSG_DATA(cmsgptr);
}
}
@@ -922,23 +897,23 @@ static void ready_callback6 (int __attribute((unused)) unused,
* This is not quite right, it could be a late packet. Do we
* care?
*/
- isDup= (ntohs(icmp->icmp6_seq) != host->seq);
+ isDup= (ntohs(icmp->icmp6_seq) != state->seq);
ping_cb(isDup ? PING_ERR_DUP : PING_ERR_NONE,
nrecv - ICMP6_HDRSIZE, nrecv + sizeof(struct ip6_hdr),
- (struct sockaddr *)&host->sin6, host->socklen,
+ (struct sockaddr *)&state->sin6, state->socklen,
(struct sockaddr *)&loc_sin6, sizeof(loc_sin6),
- ntohs(icmp->icmp6_seq), host->rcvd_ttl, &elapsed,
- host);
+ ntohs(icmp->icmp6_seq), state->rcvd_ttl, &elapsed,
+ state);
/* Update the sequence number for the next run */
- host->seq = (host->seq + 1) % 256;
+ state->seq = (state->seq + 1) % 256;
if (!isDup)
- host->got_reply= 1;
+ state->got_reply= 1;
}
else
/* Handle this condition exactly as the request has expired */
- noreply_callback (-1, -1, host);
+ noreply_callback (-1, -1, state);
done:
;
@@ -953,53 +928,18 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
int i, newsiz, delay_name_res;
uint32_t opt;
unsigned pingcount; /* must be int-sized */
- unsigned size;
+ unsigned size, interval;
sa_family_t af;
const char *hostname;
char *str_Atlas;
char *out_filename;
+ char *interface;
struct pingstate *state;
len_and_sockaddr *lsa;
FILE *fh;
if (!ping_base)
{
- int p_proto, on;
- struct protoent *protop;
- evutil_socket_t fd4, fd6;
-
- /* Check if the ICMP protocol is available on this system */
- protop = getprotobyname("icmp");
- if (protop)
- p_proto= protop->p_proto;
- else
- p_proto= IPPROTO_ICMP;
-
- /* Create an endpoint for communication using raw socket for ICMP calls */
- if ((fd4 = socket(AF_INET, SOCK_RAW, p_proto)) == -1) {
- return NULL;
- }
-
- /* Check if the ICMP6 protocol is available on this system */
- protop = getprotobyname("icmp6");
- if (protop)
- p_proto= protop->p_proto;
- else
- p_proto= IPPROTO_ICMPV6;
-
- if ((fd6 = socket(AF_INET6, SOCK_RAW, p_proto)) == -1) {
- close(fd4);
- return NULL;
- }
-
- on = 1;
- setsockopt(fd6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
- sizeof(on));
-
- on = 1;
- setsockopt(fd6, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
- sizeof(on));
-
ping_base = malloc(sizeof(*ping_base));
if (ping_base == NULL)
return (NULL);
@@ -1011,27 +951,9 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
ping_base->table= xzalloc(ping_base->tabsiz *
sizeof(*ping_base->table));
- ping_base->rawfd4 = fd4;
- ping_base->rawfd6 = fd6;
- evutil_make_socket_nonblocking(ping_base->rawfd4);
- evutil_make_socket_nonblocking(ping_base->rawfd6);
-
/* Set default values */
ping_base->pid = getpid();
- msecstotv(DEFAULT_PING_INTERVAL, &ping_base->tv_interval);
-
- /* Define the callback to handle ICMP Echo Reply and add the
- * raw file descriptor to those monitored for read events */
- event_assign(&ping_base->event4, ping_base->event_base,
- ping_base->rawfd4, EV_READ | EV_PERSIST,
- ready_callback4, ping_base);
- event_assign(&ping_base->event6, ping_base->event_base,
- ping_base->rawfd6, EV_READ | EV_PERSIST,
- ready_callback6, ping_base);
- event_add(&ping_base->event4, NULL);
- event_add(&ping_base->event6, NULL);
-
ping_base->done= 0;
}
@@ -1040,10 +962,12 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
size= 0;
str_Atlas= NULL;
out_filename= NULL;
+ interval= DEFAULT_PING_INTERVAL;
+ interface= NULL;
/* exactly one argument needed; -c NUM */
- opt_complementary = "=1:c+:s+";
+ opt_complementary = "=1:c+:s+:i+";
opt = getopt32(argv, PING_OPT_STRING, &pingcount, &size,
- &str_Atlas, &out_filename);
+ &str_Atlas, &out_filename, &interval, &interface);
hostname = argv[optind];
if (opt == 0xffffffff)
@@ -1052,6 +976,12 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
return NULL;
}
+ if (interval < 1 || interval > 60000)
+ {
+ crondlog(LVL8 "bad interval");
+ return NULL;
+ }
+
if (out_filename)
{
if (!validate_filename(out_filename, SAFE_PREFIX))
@@ -1078,10 +1008,9 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
}
}
- af= AF_UNSPEC;
if (opt & opt_4)
af= AF_INET;
- if (opt & opt_6)
+ else
af= AF_INET6;
delay_name_res= !!(opt & opt_r);
@@ -1113,6 +1042,9 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
state->base = ping_base;
state->af= af;
state->delay_name_res= delay_name_res;
+ state->interval= interval;
+ state->interface= interface;
+ state->socket= -1;
state->seq = 1;
@@ -1157,7 +1089,9 @@ static void *ping_init(int __attribute((unused)) argc, char *argv[],
static void ping_start2(void *state)
{
+ int p_proto, on, fd;
struct pingstate *pingstate;
+ char line[80];
pingstate= state;
@@ -1167,6 +1101,98 @@ static void ping_start2(void *state)
pingstate->send_error= 0;
pingstate->got_reply= 0;
+ if (pingstate->af == AF_INET)
+ {
+ /* Check if the ICMP protocol is available on this system */
+ p_proto= IPPROTO_ICMP;
+
+ /* Create an endpoint for communication using raw socket for
+ * ICMP calls */
+ if ((fd = socket(AF_INET, SOCK_RAW, p_proto)) == -1) {
+ snprintf(line, sizeof(line),
+ "{ " DBQ(error) ":" DBQ(socket failed: %s)
+ " }", strerror(errno));
+ add_str(pingstate, line);
+ report(pingstate);
+ if (pingstate->base->done)
+ pingstate->base->done(pingstate);
+ return;
+ }
+ pingstate->socket= fd;
+
+ /* Define the callback to handle ICMP Echo Reply and add the
+ * raw file descriptor to those monitored for read events */
+ event_assign(&pingstate->event, pingstate->base->event_base,
+ pingstate->socket, EV_READ | EV_PERSIST,
+ ready_callback4, state);
+ }
+ else
+ {
+ /* Check if the ICMP6 protocol is available on this system */
+ p_proto= IPPROTO_ICMPV6;
+
+ if ((fd = socket(AF_INET6, SOCK_RAW, p_proto)) == -1) {
+ snprintf(line, sizeof(line),
+ "{ " DBQ(error) ":" DBQ(socket failed: %s)
+ " }", strerror(errno));
+ add_str(pingstate, line);
+ report(pingstate);
+ if (pingstate->base->done)
+ pingstate->base->done(pingstate);
+ return;
+ }
+
+ on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
+ sizeof(on));
+
+ on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
+ sizeof(on));
+
+ pingstate->socket= fd;
+
+ /* Define the callback to handle ICMP Echo Reply and add the
+ * raw file descriptor to those monitored for read events */
+ event_assign(&pingstate->event, pingstate->base->event_base,
+ pingstate->socket, EV_READ | EV_PERSIST,
+ ready_callback6, state);
+ }
+
+ evutil_make_socket_nonblocking(pingstate->socket);
+
+ if (pingstate->interface)
+ {
+ if (bind_interface(pingstate->socket, pingstate->af,
+ pingstate->interface) == -1)
+ {
+ snprintf(line, sizeof(line),
+ "{ " DBQ(error) ":"
+ DBQ(bind to interface failed)
+ " }");
+ add_str(pingstate, line);
+ report(pingstate);
+ if (pingstate->base->done)
+ pingstate->base->done(pingstate);
+ return;
+ }
+ }
+
+ if (connect(pingstate->socket, &pingstate->sin6,
+ pingstate->socklen) == -1)
+ {
+ snprintf(line, sizeof(line),
+ "{ " DBQ(error) ":" DBQ(connect failed: %s)
+ " }", strerror(errno));
+ add_str(pingstate, line);
+ report(pingstate);
+ if (pingstate->base->done)
+ pingstate->base->done(pingstate);
+ return;
+ }
+
+ event_add(&pingstate->event, NULL);
+
ping_xmit(pingstate);
}
diff --git a/eperd/readresolv.c b/eperd/readresolv.c
index cd43bd3..0f68a37 100644
--- a/eperd/readresolv.c
+++ b/eperd/readresolv.c
@@ -110,3 +110,42 @@ void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
*resolv_max = i;
return;
}
+
+void get_local_resolvers_nocache(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
+ int *resolv_max)
+{
+
+#ifndef RESOLV_CONF
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif
+ FILE *R;
+ char buf[LINEL];
+ char *buf_start;
+ int i = 0;
+ int r;
+ struct stat sb;
+
+ r = stat(RESOLV_CONF, &sb);
+ if (r == -1)
+ {
+ crondlog(LVL8 "error accessing resolv.conf: %s",
+ strerror(errno));
+ return;
+ }
+
+ R = fopen (RESOLV_CONF, "r");
+ if (R != NULL) {
+ while ( (fgets (buf, LINEL, R)) && (i < MAXNS)) {
+ buf_start = buf;
+ if(resolv_conf_parse_line(nslist[i], buf) ) {
+ crondlog(LVL5 "parsed file %s , line %s i=%d", RESOLV_CONF, buf_start, i);
+ i++;
+ }
+ else
+ crondlog(LVL5 "ERROR failed to parse from %s i=%d, line %s", RESOLV_CONF, i, buf_start);
+ }
+ fclose (R);
+ }
+
+ *resolv_max = i;
+}
diff --git a/eperd/readresolv.h b/eperd/readresolv.h
index 4c1fa83..b418d71 100644
--- a/eperd/readresolv.h
+++ b/eperd/readresolv.h
@@ -3,3 +3,5 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
void get_local_resolvers(char nslist[MAXNS][INET6_ADDRSTRLEN * 2], int *resolv_max);
+void get_local_resolvers_nocache(char nslist[MAXNS][INET6_ADDRSTRLEN * 2],
+ int *resolv_max);
diff --git a/eperd/sslgetcert.c b/eperd/sslgetcert.c
index 2b71cc4..0a0f885 100644
--- a/eperd/sslgetcert.c
+++ b/eperd/sslgetcert.c
@@ -748,8 +748,9 @@ static void report(struct state *state)
{
fprintf(fh, DBQ(id) ":" DBQ(%s) ", "
DBQ(fw) ":%d, "
+ DBQ(lts) ":%d, "
DBQ(time) ":%ld, ",
- state->atlas, get_atlas_fw_version(),
+ state->atlas, get_atlas_fw_version(), get_timesync(),
state->gstart);
}
@@ -977,8 +978,10 @@ static int eat_certificate(struct state *state)
if (state->atlas)
{
fprintf(fh, DBQ(id) ":" DBQ(%s)
- ", " DBQ(fw) ":%d",
- state->atlas, get_atlas_fw_version());
+ ", " DBQ(fw) ":%d"
+ ", " DBQ(lts) ":%d",
+ state->atlas, get_atlas_fw_version(),
+ get_timesync());
}
fprintf(fh, "%s" DBQ(time) ":%ld",
@@ -1260,7 +1263,7 @@ static void sslgetcert_start(void *vstate)
tu_connect_to_name(&state->tu_env, state->hostname,
state->portname,
- &interval, &hints, timeout_callback,
+ &interval, &hints, NULL, timeout_callback,
reporterr, dnscount, beforeconnect,
connected, readcb, writecb);
}
diff --git a/eperd/tcputil.c b/eperd/tcputil.c
index d3d6134..355f42a 100644
--- a/eperd/tcputil.c
+++ b/eperd/tcputil.c
@@ -13,12 +13,13 @@
#include "tcputil.h"
static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx);
-static void create_bev(struct tu_env *env);
+static int create_bev(struct tu_env *env);
static void eventcb(struct bufferevent *bev, short events, void *ptr);
void tu_connect_to_name(struct tu_env *env, char *host, char *port,
struct timeval *interval,
struct evutil_addrinfo *hints,
+ char *infname,
void (*timeout_callback)(int unused, const short event, void *s),
void (*reporterr)(struct tu_env *env, enum tu_err cause,
const char *err),
@@ -30,6 +31,7 @@ void tu_connect_to_name(struct tu_env *env, char *host, char *port,
void (*writecb)(struct bufferevent *bev, void *ptr))
{
env->interval= *interval;
+ env->infname= infname;
env->reporterr= reporterr;
env->reportcount= reportcount;
env->beforeconnect= beforeconnect;
@@ -49,6 +51,7 @@ void tu_connect_to_name(struct tu_env *env, char *host, char *port,
void tu_restart_connect(struct tu_env *env)
{
+ int r;
struct bufferevent *bev;
/* Delete old bev */
@@ -59,7 +62,11 @@ void tu_restart_connect(struct tu_env *env)
}
/* And create a new one */
- create_bev(env);
+ r= create_bev(env);
+ if (r == -1)
+ {
+ return;
+ }
bev= env->bev;
/* Connect failed, try next address */
@@ -118,7 +125,7 @@ void tu_cleanup(struct tu_env *env)
static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx)
{
- int count;
+ int r, count;
struct tu_env *env;
struct bufferevent *bev;
struct evutil_addrinfo *cur;
@@ -151,7 +158,11 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx)
env->reportcount(env, count);
- create_bev(env);
+ r= create_bev(env);
+ if (r == -1)
+ {
+ return;
+ }
while (env->dns_curr)
{
@@ -192,21 +203,44 @@ static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx)
env->reporterr(env, TU_OUT_OF_ADDRS, "");
}
-static void create_bev(struct tu_env *env)
+static int create_bev(struct tu_env *env)
{
+ int af, fd;
struct bufferevent *bev;
+ af= env->dns_curr->ai_addr->sa_family;
+
bev= bufferevent_socket_new(EventBase, -1,
BEV_OPT_CLOSE_ON_FREE);
if (!bev)
{
crondlog(DIE9 "bufferevent_socket_new failed");
}
+ if (env->infname)
+ {
+ fd= socket(af, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ env->reporterr(env, TU_SOCKET_ERR,
+ "socket call failed");
+ return -1;
+ }
+
+ if (bind_interface(fd, af, env->infname) == -1)
+ {
+ env->reporterr(env, TU_SOCKET_ERR,
+ "bind_interface failed");
+ close(fd);
+ return -1;
+ }
+ bufferevent_setfd(bev, fd);
+ }
bufferevent_setcb(bev, env->readcb, env->writecb, eventcb, env);
bufferevent_enable(bev, EV_WRITE);
env->bev= bev;
env->connecting= 1;
+ return 0;
}
static void eventcb(struct bufferevent *bev, short events, void *ptr)
diff --git a/eperd/tcputil.h b/eperd/tcputil.h
index d2b11ec..da26641 100644
--- a/eperd/tcputil.h
+++ b/eperd/tcputil.h
@@ -6,7 +6,8 @@
#include <event2/event_struct.h>
-enum tu_err { TU_DNS_ERR, TU_READ_ERR, TU_CONNECT_ERR, TU_OUT_OF_ADDRS };
+enum tu_err { TU_DNS_ERR, TU_READ_ERR, TU_SOCKET_ERR, TU_CONNECT_ERR,
+ TU_OUT_OF_ADDRS };
struct tu_env
{
char dnsip;
@@ -15,6 +16,7 @@ struct tu_env
struct evutil_addrinfo *dns_curr;
struct bufferevent *bev;
struct timeval interval;
+ char *infname;
struct event timer;
void (*reporterr)(struct tu_env *env, enum tu_err cause,
const char *str);
@@ -29,6 +31,7 @@ struct tu_env
void tu_connect_to_name(struct tu_env *env, char *host, char *port,
struct timeval *timeout,
struct evutil_addrinfo *hints,
+ char *infname,
void (*timeout_callback)(int unused, const short event, void *env),
void (*reporterr)(struct tu_env *env, enum tu_err cause,
const char *err),
diff --git a/eperd/traceroute.c b/eperd/traceroute.c
index d655e44..a3d0f24 100644
--- a/eperd/traceroute.c
+++ b/eperd/traceroute.c
@@ -28,7 +28,7 @@
#define uh_sum check
#endif
-#define TRACEROUTE_OPT_STRING ("!46IUFrTa:c:f:g:m:p:w:z:A:O:S:H:D:")
+#define TRACEROUTE_OPT_STRING ("!46IUFrTa:c:f:g:i:m:p:w:z:A:O:S:H:D:")
#define OPT_4 (1 << 0)
#define OPT_6 (1 << 1)
@@ -63,21 +63,8 @@ struct trtbase
{
struct event_base *event_base;
- int v4icmp_rcv;
- int v6icmp_rcv;
- int v4icmp_snd;
- int v6icmp_snd;
- int v4tcp_rcv;
- int v6tcp_rcv;
- int v4udp_snd;
-
int my_pid;
- struct event event4;
- struct event tcp_event4;
- struct event event6;
- struct event tcp_event6;
-
struct trtstate **table;
int tabsiz;
@@ -95,9 +82,10 @@ struct trtstate
/* Parameters */
char *atlas;
char *hostname;
- const char *destportstr;
+ char *destportstr;
char *out_filename;
- char do_Xicmp;
+ char *interface;
+ char do_icmp;
char do_tcp;
char do_udp;
char do_v6;
@@ -128,6 +116,13 @@ struct trtstate
uint16_t paris;
uint16_t seq;
unsigned short curpacksize;
+
+ int socket_icmp; /* Socket for sending and receiving
+ * ICMPs */
+ struct event event_icmp; /* Event for this socket */
+ int socket_tcp; /* Socket for sending and receiving
+ * raw TCP */
+ struct event event_tcp; /* Event for this socket */
uint8_t last_response_hop; /* Hop at which we last got something
* back.
@@ -160,6 +155,7 @@ struct trtstate
char *result;
size_t reslen;
size_t resmax;
+ char open_result;
};
static struct trtbase *trt_base;
@@ -191,6 +187,8 @@ struct v6info
struct timeval tv;
};
+static int create_socket(struct trtstate *state, int do_tcp);
+
#define OPT_PAD1 0
#define OPT_PADN 1
static void do_hbh_dest_opt(struct trtbase *base, int sock, int hbh_dest,
@@ -387,9 +385,11 @@ static void report(struct trtstate *state)
{
fprintf(fh, DBQ(id) ":" DBQ(%s)
", " DBQ(fw) ":%d"
+ ", " DBQ(lts) ":%d"
", " DBQ(time) ":%ld"
", " DBQ(endtime) ":%ld, ",
state->atlas, get_atlas_fw_version(),
+ get_timesync(),
state->starttime,
(long)time(NULL));
}
@@ -412,7 +412,7 @@ static void report(struct trtstate *state)
fprintf(fh, ", " DBQ(src_addr) ":" DBQ(%s), namebuf);
}
- if (state->do_Xicmp)
+ if (state->do_icmp)
proto= "ICMP";
else if (state->do_tcp)
proto= "TCP";
@@ -430,13 +430,29 @@ static void report(struct trtstate *state)
state->paris % state->parismod);
}
fprintf(fh, ", \"result\": [ %s ] }\n", state->result);
+
free(state->result);
state->result= NULL;
- state->busy= 0;
if (state->out_filename)
fclose(fh);
+ /* Kill the event and close socket */
+ if (state->socket_icmp != -1)
+ {
+ event_del(&state->event_icmp);
+ close(state->socket_icmp);
+ state->socket_icmp= -1;
+ }
+ if (state->socket_tcp != -1)
+ {
+ event_del(&state->event_tcp);
+ close(state->socket_tcp);
+ state->socket_tcp= -1;
+ }
+
+ state->busy= 0;
+
if (state->base->done)
state->base->done(state);
}
@@ -498,8 +514,9 @@ static void send_pkt(struct trtstate *state)
}
snprintf(line, sizeof(line),
- ", { \"hop\":%d, \"result\": [ ", state->hop);
+ ", { " DBQ(hop) ":%d, " DBQ(result) ": [ ", state->hop);
add_str(state, line);
+ state->open_result= 0;
}
state->seq++;
@@ -628,21 +645,21 @@ static void send_pkt(struct trtstate *state)
}
}
}
- else if (state->do_Xicmp)
+ else if (state->do_icmp)
{
/* Set hop count */
- setsockopt(base->v6icmp_snd, SOL_IPV6,
+ setsockopt(state->socket_icmp, SOL_IPV6,
IPV6_UNICAST_HOPS, &hop, sizeof(hop));
/* Set/clear don't fragment */
on= (state->dont_fragment ? IPV6_PMTUDISC_DO :
IPV6_PMTUDISC_DONT);
- setsockopt(base->v6icmp_snd, IPPROTO_IPV6,
+ setsockopt(state->socket_icmp, IPPROTO_IPV6,
IPV6_MTU_DISCOVER, &on, sizeof(on));
- do_hbh_dest_opt(base, base->v6icmp_snd, 0 /* hbh */,
+ do_hbh_dest_opt(base, state->socket_icmp, 0 /* hbh */,
state->hbhoptsize);
- do_hbh_dest_opt(base, base->v6icmp_snd, 1 /* dest */,
+ do_hbh_dest_opt(base, state->socket_icmp, 1 /* dest */,
state->destoptsize);
icmp6_hdr= (struct icmp6_hdr *)base->packet;
@@ -708,7 +725,7 @@ static void send_pkt(struct trtstate *state)
memset(&sin6copy, '\0', sizeof(sin6copy));
sin6copy.sin6_family= AF_INET6;
sin6copy.sin6_addr= state->sin6.sin6_addr;
- r= sendto(base->v6icmp_snd, base->packet, len, 0,
+ r= sendto(state->socket_icmp, base->packet, len, 0,
(struct sockaddr *)&sin6copy,
sizeof(sin6copy));
@@ -996,7 +1013,7 @@ static void send_pkt(struct trtstate *state)
}
}
}
- else if (state->do_Xicmp)
+ else if (state->do_icmp)
{
hop= state->hop;
@@ -1044,16 +1061,16 @@ static void send_pkt(struct trtstate *state)
#endif
/* Set hop count */
- setsockopt(base->v4icmp_snd, IPPROTO_IP, IP_TTL,
+ setsockopt(state->socket_icmp, IPPROTO_IP, IP_TTL,
&hop, sizeof(hop));
/* Set/clear don't fragment */
on= (state->dont_fragment ? IP_PMTUDISC_DO :
IP_PMTUDISC_DONT);
- setsockopt(base->v4icmp_snd, IPPROTO_IP,
+ setsockopt(state->socket_icmp, IPPROTO_IP,
IP_MTU_DISCOVER, &on, sizeof(on));
- r= sendto(base->v4icmp_snd, base->packet, len, 0,
+ r= sendto(state->socket_icmp, base->packet, len, 0,
(struct sockaddr *)&state->sin6,
state->socklen);
@@ -1224,9 +1241,10 @@ static void send_pkt(struct trtstate *state)
}
}
- if (state->sent)
+ if (state->open_result)
add_str(state, " }, ");
add_str(state, "{ ");
+ state->open_result= 0;
/* Increment packets sent */
state->sent++;
@@ -1344,10 +1362,11 @@ static void ready_callback4(int __attribute((unused)) unused,
gettimeofday(&now, NULL);
- base= s;
+ state= s;
+ base= state->base;
slen= sizeof(remote);
- nrecv= recvfrom(base->v4icmp_rcv, base->packet, sizeof(base->packet),
+ nrecv= recvfrom(state->socket_icmp, base->packet, sizeof(base->packet),
MSG_DONTWAIT, (struct sockaddr *)&remote, &slen);
if (nrecv == -1)
{
@@ -1412,9 +1431,8 @@ static void ready_callback4(int __attribute((unused)) unused,
*/
ind= ntohl(etcp->seq) >> 16;
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET)
state= NULL;
if (state && !state->do_tcp)
@@ -1453,6 +1471,9 @@ static void ready_callback4(int __attribute((unused)) unused,
/* Sequence number is in seq field */
seq= ntohl(etcp->seq) & 0xffff;
+ if (state->open_result)
+ add_str(state, " }, { ");
+
if (seq != state->seq)
{
if (seq > state->seq)
@@ -1467,14 +1488,14 @@ static void ready_callback4(int __attribute((unused)) unused,
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, " " DBQ(dup) ":true");
}
if (!late && !isDup)
@@ -1611,12 +1632,11 @@ printf("curpacksize: %d\n", state->curpacksize);
*/
ind= ntohs(eudp->uh_sport) - SRC_BASE_PORT;
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET)
state= NULL;
- if (state && state->do_Xicmp)
+ if (state && state->do_icmp)
state= NULL;
if (!state)
@@ -1665,6 +1685,9 @@ printf("curpacksize: %d\n", state->curpacksize);
seq= ntohs(eudp->uh_dport)-BASE_PORT;
}
+ if (state->open_result)
+ add_str(state, " }, { ");
+
if (seq != state->seq)
{
if (seq > state->seq)
@@ -1679,14 +1702,14 @@ printf("curpacksize: %d\n", state->curpacksize);
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, " " DBQ(dup) ":true");
}
if (!late && !isDup)
@@ -1839,8 +1862,7 @@ printf("curpacksize: %d\n", state->curpacksize);
return;
}
- state= base->table[ind];
- if (!state)
+ if (ind != state->index)
{
/* Nothing here */
printf(
@@ -1855,7 +1877,7 @@ printf("curpacksize: %d\n", state->curpacksize);
return;
}
- if (!state->do_Xicmp)
+ if (!state->do_icmp)
{
printf(
"ready_callback4: index (%d) is not doing ICMP\n",
@@ -1880,6 +1902,9 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
state->hostname);
}
+ if (state->open_result)
+ add_str(state, " }, { ");
+
late= 0;
isDup= 0;
seq= ntohs(eicmp->icmp_seq);
@@ -1897,14 +1922,14 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
if (!late && !isDup)
@@ -2072,8 +2097,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
}
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -2109,8 +2133,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
return;
}
- state= base->table[ind];
- if (!state)
+ if (ind != state->index)
{
/* Nothing here */
printf(
@@ -2134,6 +2157,9 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
return;
}
+ if (state->open_result)
+ add_str(state, " }, { ");
+
late= 0;
isDup= 0;
seq= ntohs(icmp->icmp_seq);
@@ -2150,14 +2176,14 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
if (memcmp(&ip->ip_dst,
@@ -2195,8 +2221,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
/* Done */
state->done= 1;
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -2245,10 +2270,11 @@ static void ready_tcp4(int __attribute((unused)) unused,
gettimeofday(&now, NULL);
- base= s;
+ state= s;
+ base= state->base;
slen= sizeof(remote);
- nrecv= recvfrom(base->v4tcp_rcv, base->packet, sizeof(base->packet),
+ nrecv= recvfrom(state->socket_tcp, base->packet, sizeof(base->packet),
MSG_DONTWAIT, (struct sockaddr *)&remote, &slen);
if (nrecv == -1)
{
@@ -2279,9 +2305,8 @@ static void ready_tcp4(int __attribute((unused)) unused,
/* We store the id in high order 16 bits of the sequence number */
ind= ntohl(tcphdr->ack_seq) >> 16;
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET)
state= NULL;
if (state && !state->do_tcp)
@@ -2306,6 +2331,9 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
late= 0;
isDup= 0;
+ if (state->open_result)
+ add_str(state, " }, { ");
+
/* Only check if the ack is without 64k of what we expect */
seq= ntohl(tcphdr->ack_seq) & 0xffff;
if (seq-state->seq > 0x2000)
@@ -2322,14 +2350,14 @@ printf("got seq %d, expected %d\n", seq, state->seq);
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 +
@@ -2368,8 +2396,7 @@ printf("got seq %d, expected %d\n", seq, state->seq);
/* Done */
state->done= 1;
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -2411,7 +2438,8 @@ static void ready_tcp6(int __attribute((unused)) unused,
gettimeofday(&now, NULL);
- base= s;
+ state= s;
+ base= state->base;
iov[0].iov_base= base->packet;
iov[0].iov_len= sizeof(base->packet);
@@ -2423,7 +2451,7 @@ static void ready_tcp6(int __attribute((unused)) unused,
msg.msg_controllen= sizeof(cmsgbuf);
msg.msg_flags= 0; /* Not really needed */
- nrecv= recvmsg(base->v6tcp_rcv, &msg, MSG_DONTWAIT);
+ nrecv= recvmsg(state->socket_tcp, &msg, MSG_DONTWAIT);
if (nrecv == -1)
{
/* Strange, read error */
@@ -2463,9 +2491,8 @@ static void ready_tcp6(int __attribute((unused)) unused,
/* We store the id in high order 16 bits of the sequence number */
ind= ntohl(tcphdr->ack_seq) >> 16;
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET6)
state= NULL;
if (state && !state->do_tcp)
@@ -2488,6 +2515,9 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
late= 0;
isDup= 0;
+ if (state->open_result)
+ add_str(state, " }, { ");
+
/* Only check if the ack is within 64k of what we expect */
seq= ntohl(tcphdr->ack_seq) & 0xffff;
if (seq-state->seq > 0x2000)
@@ -2504,14 +2534,14 @@ printf("got seq %d, expected %d\n", seq, state->seq);
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
ms= (now.tv_sec-state->xmit_time.tv_sec)*1000 +
@@ -2549,8 +2579,7 @@ printf("got seq %d, expected %d\n", seq, state->seq);
/* Done */
state->done= 1;
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -2599,7 +2628,8 @@ static void ready_callback6(int __attribute((unused)) unused,
gettimeofday(&now, NULL);
- base= s;
+ state= s;
+ base= state->base;
iov[0].iov_base= base->packet;
iov[0].iov_len= sizeof(base->packet);
@@ -2611,7 +2641,7 @@ static void ready_callback6(int __attribute((unused)) unused,
msg.msg_controllen= sizeof(cmsgbuf);
msg.msg_flags= 0; /* Not really needed */
- nrecv= recvmsg(base->v6icmp_rcv, &msg, MSG_DONTWAIT);
+ nrecv= recvmsg(state->socket_icmp, &msg, MSG_DONTWAIT);
if (nrecv == -1)
{
/* Strange, read error */
@@ -2695,7 +2725,7 @@ static void ready_callback6(int __attribute((unused)) unused,
#endif
return;
}
- opthdr= (struct ip6_ext *)&eip[1];
+ opthdr= (struct ip6_ext *)ptr;
hbhoptsize= 8*opthdr->ip6e_len;
optlen= hbhoptsize+8;
if (nrecv < sizeof(*icmp) + sizeof(*eip) +
@@ -2704,7 +2734,7 @@ static void ready_callback6(int __attribute((unused)) unused,
/* Does not contain the full header */
return;
}
- ehdrsiz= optlen;
+ ehdrsiz += optlen;
nxt= opthdr->ip6e_nxt;
ptr= ((char *)opthdr)+optlen;
}
@@ -2723,7 +2753,7 @@ static void ready_callback6(int __attribute((unused)) unused,
#endif
return;
}
- frag= (struct ip6_frag *)&eip[1];
+ frag= (struct ip6_frag *)ptr;
if ((ntohs(frag->ip6f_offlg) & ~3) != 0)
{
/* Not first fragment, just ignore
@@ -2731,7 +2761,7 @@ static void ready_callback6(int __attribute((unused)) unused,
*/
return;
}
- ehdrsiz= sizeof(*frag);
+ ehdrsiz += sizeof(*frag);
nxt= frag->ip6f_nxt;
ptr= &frag[1];
}
@@ -2750,7 +2780,7 @@ static void ready_callback6(int __attribute((unused)) unused,
#endif
return;
}
- opthdr= (struct ip6_ext *)&eip[1];
+ opthdr= (struct ip6_ext *)ptr;
dstoptsize= 8*opthdr->ip6e_len;
optlen= dstoptsize+8;
if (nrecv < sizeof(*icmp) + sizeof(*eip) +
@@ -2759,7 +2789,7 @@ static void ready_callback6(int __attribute((unused)) unused,
/* Does not contain the full header */
return;
}
- ehdrsiz= optlen;
+ ehdrsiz += optlen;
nxt= opthdr->ip6e_nxt;
ptr= ((char *)opthdr)+optlen;
}
@@ -2838,9 +2868,8 @@ static void ready_callback6(int __attribute((unused)) unused,
ind= ntohl(v6info->id);
}
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET6)
state= NULL;
@@ -2849,7 +2878,7 @@ static void ready_callback6(int __attribute((unused)) unused,
{
if ((etcp && !state->do_tcp) ||
(eudp && !state->do_udp) ||
- (eicmp && !state->do_Xicmp))
+ (eicmp && !state->do_icmp))
{
state= NULL;
}
@@ -2888,6 +2917,10 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
else
seq= ntohl(v6info->seq);
+
+ if (state->open_result)
+ add_str(state, " }, { ");
+
if (seq != state->seq)
{
if (seq > state->seq)
@@ -2902,13 +2935,13 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
} else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
if (!late && !isDup)
@@ -3042,16 +3075,19 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
state->done= 1;
switch(icmp->icmp6_code)
{
- case ICMP6_DST_UNREACH_NOROUTE:
+ case ICMP6_DST_UNREACH_NOROUTE: /* 0 */
add_str(state, ", \"err\":\"N\"");
break;
- case ICMP6_DST_UNREACH_ADDR:
- add_str(state, ", \"err\":\"H\"");
+ case ICMP6_DST_UNREACH_ADMIN: /* 1 */
+ add_str(state, ", \"err\":\"A\"");
break;
- case ICMP6_DST_UNREACH_NOPORT:
+ case ICMP6_DST_UNREACH_BEYONDSCOPE: /* 2 */
+ add_str(state, ", \"err\":\"h\"");
break;
- case ICMP6_DST_UNREACH_ADMIN:
- add_str(state, ", \"err\":\"A\"");
+ case ICMP6_DST_UNREACH_ADDR: /* 3 */
+ add_str(state, ", \"err\":\"H\"");
+ break;
+ case ICMP6_DST_UNREACH_NOPORT: /* 4 */
break;
default:
snprintf(line, sizeof(line),
@@ -3110,8 +3146,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
}
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -3153,14 +3188,12 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
ind= ntohl(v6info->id);
- state= NULL;
- if (ind >= 0 && ind < base->tabsiz)
- state= base->table[ind];
-
+ if (ind != state->index)
+ state= NULL;
if (state && state->sin6.sin6_family != AF_INET6)
state= NULL;
- if (state && !state->do_Xicmp)
+ if (state && !state->do_icmp)
{
state= NULL;
}
@@ -3189,6 +3222,9 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
return;
}
+ if (state->open_result)
+ add_str(state, " }, { ");
+
late= 0;
isDup= 0;
seq= ntohl(v6info->seq);
@@ -3204,14 +3240,14 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
}
late= 1;
- snprintf(line, sizeof(line), "\"late\":%d",
+ snprintf(line, sizeof(line), DBQ(late) ":%d",
state->seq-seq);
add_str(state, line);
}
else if (state->gotresp)
{
isDup= 1;
- add_str(state, " }, { \"dup\":true");
+ add_str(state, DBQ(dup) ":true");
}
if (!late && !isDup)
@@ -3260,8 +3296,7 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
sizeof(buf)), state->hop);
#endif
- if (late)
- add_str(state, " }, { ");
+ state->open_result= 1;
if (!late && !isDup)
{
@@ -3296,7 +3331,6 @@ printf("%s, %d: sin6_family = %d\n", __FILE__, __LINE__, state->sin6.sin6_family
static struct trtbase *traceroute_base_new(struct event_base
*event_base)
{
- int on;
struct trtbase *base;
base= xzalloc(sizeof(*base));
@@ -3306,40 +3340,8 @@ static struct trtbase *traceroute_base_new(struct event_base
base->tabsiz= 10;
base->table= xzalloc(base->tabsiz * sizeof(*base->table));
- base->v4icmp_rcv= xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- base->v6icmp_rcv= xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- base->v4icmp_snd= xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- base->v6icmp_snd= xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- base->v4tcp_rcv= xsocket(AF_INET, SOCK_RAW, IPPROTO_TCP);
- base->v6tcp_rcv= xsocket(AF_INET6, SOCK_RAW, IPPROTO_TCP);
- base->v4udp_snd= xsocket(AF_INET, SOCK_DGRAM, 0);
-
base->my_pid= getpid();
- on = 1;
- setsockopt(base->v6icmp_rcv, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- &on, sizeof(on));
-
- on = 1;
- setsockopt(base->v6icmp_rcv, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
- &on, sizeof(on));
- on = 1;
- setsockopt(base->v6tcp_rcv, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
- &on, sizeof(on));
-
- event_assign(&base->event4, base->event_base, base->v4icmp_rcv,
- EV_READ | EV_PERSIST, ready_callback4, base);
- event_assign(&base->tcp_event4, base->event_base, base->v4tcp_rcv,
- EV_READ | EV_PERSIST, ready_tcp4, base);
- event_assign(&base->event6, base->event_base, base->v6icmp_rcv,
- EV_READ | EV_PERSIST, ready_callback6, base);
- event_assign(&base->tcp_event6, base->event_base, base->v6tcp_rcv,
- EV_READ | EV_PERSIST, ready_tcp6, base);
- event_add(&base->event4, NULL);
- event_add(&base->tcp_event4, NULL);
- event_add(&base->event6, NULL);
- event_add(&base->tcp_event6, NULL);
-
return base;
}
@@ -3356,7 +3358,12 @@ static void noreply_callback(int __attribute((unused)) unused,
#endif
if (!state->gotresp)
- add_str(state, "\"x\":\"*\"");
+ {
+ if (state->open_result)
+ add_str(state, " }, { ");
+ add_str(state, DBQ(x) ":" DBQ(*));
+ state->open_result= 1;
+ }
send_pkt(state);
}
@@ -3375,6 +3382,7 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[],
const char *hostname;
char *out_filename;
const char *destportstr;
+ char *interface;
char *check;
struct trtstate *state;
sa_family_t af;
@@ -3392,12 +3400,15 @@ static void *traceroute_init(int __attribute((unused)) argc, char *argv[],
count= 3;
firsthop= 1;
gaplimit= 5;
+ interface= NULL;
maxhops= 32;
maxpacksize= 40;
destportstr= "80";
duptimeout= 10;
timeout= 1000;
parismod= 16;
+ hbhoptsize= 0;
+ destoptsize= 0;
str_Atlas= NULL;
out_filename= NULL;
opt_complementary = "=1:4--6:i--u:a+:c+:f+:g+:m+:w+:z+:S+:H+:D+";
@@ -3406,7 +3417,8 @@ for (i= 0; argv[i] != NULL; i++)
printf("argv[%d] = '%s'\n", i, argv[i]);
opt = getopt32(argv, TRACEROUTE_OPT_STRING, &parismod, &count,
- &firsthop, &gaplimit, &maxhops, &destportstr, &timeout,
+ &firsthop, &gaplimit, &interface, &maxhops, &destportstr,
+ &timeout,
&duptimeout, &str_Atlas, &out_filename, &maxpacksize,
&hbhoptsize, &destoptsize);
hostname = argv[optind];
@@ -3483,12 +3495,13 @@ for (i= 0; argv[i] != NULL; i++)
state->maxpacksize= maxpacksize;
state->maxhops= maxhops;
state->gaplimit= gaplimit;
- state->destportstr= destportstr;
+ state->interface= interface;
+ state->destportstr= strdup(destportstr);
state->duptimeout= duptimeout*1000;
state->timeout= timeout*1000;
state->atlas= str_Atlas ? strdup(str_Atlas) : NULL;
state->hostname= strdup(hostname);
- state->do_Xicmp= do_icmp;
+ state->do_icmp= do_icmp;
state->do_tcp= do_tcp;
state->do_udp= do_udp;
state->do_v6= do_v6;
@@ -3548,15 +3561,10 @@ for (i= 0; argv[i] != NULL; i++)
static void traceroute_start2(void *state)
{
- int r, serrno;
struct trtstate *trtstate;
- struct trtbase *trtbase;
- struct sockaddr_in loc_sa4;
- struct sockaddr_in6 loc_sa6;
char line[80];
trtstate= state;
- trtbase= trtstate->base;
if (trtstate->busy)
{
@@ -3586,231 +3594,235 @@ static void traceroute_start2(void *state)
trtstate->resmax= 80;
trtstate->result= xmalloc(trtstate->resmax);
trtstate->reslen= 0;
+ trtstate->open_result= 0;
trtstate->starttime= time(NULL);
+ trtstate->socket_icmp= -1;
+ trtstate->socket_tcp= -1;
+
snprintf(line, sizeof(line), "{ \"hop\":%d", trtstate->hop);
add_str(trtstate, line);
- if (trtstate->do_Xicmp)
+ if (trtstate->do_icmp)
{
+ if (create_socket(trtstate, 0 /*do_tcp*/) == -1)
+ return;
+ }
+ else if (trtstate->do_udp)
+ {
+ if (create_socket(trtstate, 0 /*do_tcp*/) == -1)
+ return;
if (trtstate->do_v6)
{
- memset(&loc_sa6, '\0', sizeof(loc_sa6));
- loc_sa6.sin6_family= AF_INET;
-
- r= connect(trtbase->v6icmp_snd,
- (struct sockaddr *)&trtstate->sin6,
- trtstate->socklen);
-#if 0
- { errno= ENOSYS; r= -1; }
-#endif
- if (r == -1)
- {
- serrno= errno;
-
- snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- return;
- }
- trtstate->loc_socklen= sizeof(trtstate->loc_sin6);
- if (getsockname(trtbase->v6icmp_snd,
- &trtstate->loc_sin6,
- &trtstate->loc_socklen) == -1)
- {
- crondlog(DIE9 "getsockname failed");
- }
-#if 0
- printf("Got localname: %s\n",
- inet_ntop(AF_INET6,
- &trtstate->loc_sin6.sin6_addr,
- buf, sizeof(buf)));
-#endif
+ trtstate->loc_sin6.sin6_port= htons(SRC_BASE_PORT +
+ trtstate->index);
}
else
{
- memset(&loc_sa4, '\0', sizeof(loc_sa4));
- loc_sa4.sin_family= AF_INET;
- ((struct sockaddr_in *)&trtstate->sin6)->sin_port=
- htons(0x8000);
-
- r= connect(trtbase->v4icmp_snd,
- (struct sockaddr *)&trtstate->sin6,
- trtstate->socklen);
-#if 0
- { errno= ENOSYS; r= -1; }
-#endif
- if (r == -1)
- {
- serrno= errno;
-
- snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- return;
- }
- trtstate->loc_socklen= sizeof(trtstate->loc_sin6);
- if (getsockname(trtbase->v4icmp_snd,
- &trtstate->loc_sin6,
- &trtstate->loc_socklen) == -1)
- {
- crondlog(DIE9 "getsockname failed");
- }
-#if 0
- printf("Got localname: %s\n",
- inet_ntoa(((struct sockaddr_in *)
- &trtstate->loc_sin6)->sin_addr));
-#endif
+ ((struct sockaddr_in *)(&trtstate->loc_sin6))->
+ sin_port= htons(SRC_BASE_PORT +
+ trtstate->index);
}
}
- else
+ else if (trtstate->do_tcp)
{
+ if (create_socket(trtstate, 1 /*do_tcp*/) == -1)
+ return;
+
if (trtstate->do_v6)
{
- int sock;
+ trtstate->loc_sin6.sin6_port= htons(SRC_BASE_PORT +
+ trtstate->index);
+ }
+ else
+ {
+ ((struct sockaddr_in *)(&trtstate->loc_sin6))->
+ sin_port= htons(SRC_BASE_PORT +
+ trtstate->index);
+ }
+ }
- memset(&loc_sa6, '\0', sizeof(loc_sa6));
- loc_sa6.sin6_family= AF_INET6;
- loc_sa6.sin6_port= htons(SRC_BASE_PORT +
- trtstate->index);;
+ add_str(trtstate, ", \"result\": [ ");
- sock= socket(AF_INET6, SOCK_DGRAM, 0);
- if (sock == -1)
- {
- crondlog(DIE9 "socket failed");
- }
- r= bind(sock, (struct sockaddr *)&loc_sa6,
- sizeof(loc_sa6));
- if (r == -1)
- {
- serrno= errno;
+ send_pkt(trtstate);
+}
- snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(bind failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- close(sock);
- return;
- }
+static int create_socket(struct trtstate *state, int do_tcp)
+{
+ int af, type, protocol;
+ int r, on, serrno;
+ char line[80];
+
+ af= (state->do_v6 ? AF_INET6 : AF_INET);
+ type= SOCK_RAW;
+ protocol= (af == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP);
- r= connect(sock, (struct sockaddr *)&trtstate->sin6,
- trtstate->socklen);
+ state->socket_icmp= xsocket(af, type, protocol);
+ if (state->socket_icmp == -1)
+ {
+ serrno= errno;
+
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(socket failed: %s) " }",
+ strerror(serrno));
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
+
+ if (state->interface)
+ {
+ if (bind_interface(state->socket_icmp,
+ af, state->interface) == -1)
+ {
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(bind_interface failed) " }");
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
+ }
+
+ r= connect(state->socket_icmp,
+ (struct sockaddr *)&state->sin6,
+ state->socklen);
#if 0
{ errno= ENOSYS; r= -1; }
#endif
- if (r == -1)
- {
- serrno= errno;
-
- snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- return;
- }
-
- trtstate->loc_socklen= sizeof(trtstate->loc_sin6);
- if (getsockname(sock,
- &trtstate->loc_sin6,
- &trtstate->loc_socklen) == -1)
- {
- crondlog(DIE9 "getsockname failed");
- }
+ if (r == -1)
+ {
+ serrno= errno;
- close(sock);
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
+ strerror(serrno));
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
+ state->loc_socklen= sizeof(state->loc_sin6);
+ if (getsockname(state->socket_icmp,
+ &state->loc_sin6,
+ &state->loc_socklen) == -1)
+ {
+ crondlog(DIE9 "getsockname failed");
+ }
#if 0
- printf("Got localname: %s:%d\n",
- inet_ntop(AF_INET6,
- &trtstate->loc_sin6.sin6_addr,
- buf, sizeof(buf)),
- ntohs(((struct sockaddr_in *)&trtstate->
- loc_sin6)->sin_port));
+ printf("Got localname: %s\n",
+ inet_ntop(AF_INET6,
+ &state->loc_sin6.sin6_addr,
+ buf, sizeof(buf)));
#endif
- }
- else
+
+ close(state->socket_icmp);
+ state->socket_icmp= xsocket(af, type,
+ protocol);
+ if (state->socket_icmp == -1)
+ {
+ serrno= errno;
+
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(socket failed: %s) " }",
+ strerror(serrno));
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
+
+ if (af == AF_INET6)
+ {
+ on = 1;
+ setsockopt(state->socket_icmp, IPPROTO_IPV6,
+ IPV6_RECVPKTINFO, &on, sizeof(on));
+
+ on = 1;
+ setsockopt(state->socket_icmp, IPPROTO_IPV6,
+ IPV6_RECVHOPLIMIT, &on, sizeof(on));
+ }
+
+ if (state->interface)
+ {
+ if (bind_interface(state->socket_icmp,
+ af, state->interface) == -1)
{
- int sock;
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(bind_interface failed) " }");
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
+ }
- memset(&loc_sa4, '\0', sizeof(loc_sa4));
- loc_sa4.sin_family= AF_INET;
+ event_assign(&state->event_icmp, state->base->event_base,
+ state->socket_icmp,
+ EV_READ | EV_PERSIST,
+ (af == AF_INET6 ? ready_callback6 : ready_callback4),
+ state);
+ event_add(&state->event_icmp, NULL);
- loc_sa4.sin_port= htons(SRC_BASE_PORT +
- trtstate->index);;
+ if (do_tcp)
+ {
+ state->socket_tcp= xsocket(af, SOCK_RAW,
+ IPPROTO_TCP);
+ if (state->socket_tcp == -1)
+ {
+ serrno= errno;
- if (!trtstate->do_tcp)
- {
- /* Also set destination port */
- ((struct sockaddr_in *)&trtstate->sin6)->
- sin_port= htons(BASE_PORT);
- }
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(socket failed: %s) " }",
+ strerror(serrno));
+ add_str(state, line);
+ report(state);
+ return -1;
+ }
- sock= socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == -1)
- {
- crondlog(DIE9 "socket failed");
- }
- r= bind(sock, (struct sockaddr *)&loc_sa4,
- sizeof(loc_sa4));
-#if 0
- { errno= ENOSYS; r= -1; }
-#endif
- if (r == -1)
- {
- serrno= errno;
+ if (af == AF_INET6)
+ {
+ on = 1;
+ setsockopt(state->socket_tcp, IPPROTO_IPV6,
+ IPV6_RECVHOPLIMIT, &on, sizeof(on));
+ }
+ if (state->interface)
+ {
+ if (bind_interface(state->socket_tcp,
+ af, state->interface) == -1)
+ {
snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(bind failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- close(sock);
- return;
+ ", " DBQ(error) ":" DBQ(bind_interface failed) " }");
+ add_str(state, line);
+ report(state);
+ return -1;
}
+ }
- r= connect(sock, (struct sockaddr *) &trtstate->sin6,
- trtstate->socklen);
+ r= connect(state->socket_tcp,
+ (struct sockaddr *)&state->sin6,
+ state->socklen);
#if 0
{ errno= ENOSYS; r= -1; }
#endif
- if (r == -1)
- {
- serrno= errno;
+ if (r == -1)
+ {
+ serrno= errno;
- snprintf(line, sizeof(line),
- ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
- strerror(serrno));
- add_str(trtstate, line);
- report(trtstate);
- close(sock);
- return;
- }
- trtstate->loc_socklen= sizeof(trtstate->loc_sin6);
- if (getsockname(sock,
- &trtstate->loc_sin6,
- &trtstate->loc_socklen) == -1)
- {
- crondlog(DIE9 "getsockname failed");
- }
- close(sock);
-#if 0
- printf("Got localname: %s:%d\n",
- inet_ntoa(((struct sockaddr_in *)
- &trtstate->loc_sin6)->sin_addr),
- ntohs(((struct sockaddr_in *)&trtstate->
- loc_sin6)->sin_port));
-#endif
+ snprintf(line, sizeof(line),
+ ", " DBQ(error) ":" DBQ(connect failed: %s) " }",
+ strerror(serrno));
+ add_str(state, line);
+ report(state);
+ return -1;
}
- }
- add_str(trtstate, ", \"result\": [ ");
+ event_assign(&state->event_tcp, state->base->event_base,
+ state->socket_tcp,
+ EV_READ | EV_PERSIST,
+ (af == AF_INET6 ? ready_tcp6 : ready_tcp4),
+ state);
+ event_add(&state->event_tcp, NULL);
+ }
- send_pkt(trtstate);
+ return 0;
}
static void dns_cb(int result, struct evutil_addrinfo *res, void *ctx)
@@ -3934,6 +3946,8 @@ static int traceroute_delete(void *state)
trtstate->atlas= NULL;
free(trtstate->hostname);
trtstate->hostname= NULL;
+ free(trtstate->destportstr);
+ trtstate->destportstr= NULL;
free(trtstate->out_filename);
trtstate->out_filename= NULL;
diff --git a/include/applets.h b/include/applets.h
index 128d8d9..829ba14 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -320,7 +320,7 @@ USE_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER,
USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_RPTRA6(APPLET(rptra6, _BB_DIR_BIN, _BB_SUID_NEVER))
-USE_RPTADDR6(APPLET(rptaddr6, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_RPTADDRS(APPLET(rptaddrs, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_RTCWAKE(APPLET(rtcwake, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts))
diff --git a/include/libbb.h b/include/libbb.h
index d5c3178..598e74e 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -314,6 +314,8 @@ extern char *bb_get_last_path_component_nostrip(const char *path) FAST_FUNC;
extern int validate_filename(const char *path, const char *prefix);
extern int validate_atlas_id(const char *atlas_id);
extern int get_probe_id(void);
+extern int get_timesync(void);
+extern int bind_interface(int socket, int af, char *name);
int ndelay_on(int fd) FAST_FUNC;
int ndelay_off(int fd) FAST_FUNC;
diff --git a/include/usage.h b/include/usage.h
index ea3b78b..c4953bc 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1062,8 +1062,8 @@
#define evtraceroute_trivial_usage \
"-[46FIrTU] [-a <paris mod>] [-c <count>] [-f <hop>]" \
-"\n [-g <gap>] [-m <hop>] [-p <port>] [-w <ms>] [-z <ms>] [-A <string>] [-O <file>]" \
-"\n [-S <size>]"
+"\n [-g <gap>] [-m <hop>] [-p <port>] [-w <ms>] [-z <ms>] [-A <string>]" \
+"\n [-O <file>] [-S <size>] [-H <hbh size>] [-D <dest. opt. size>]"
#define evtraceroute_full_usage "\n" \
"\n -4 Use IPv4 (default)" \
@@ -1082,6 +1082,8 @@
"\n -w <timeout> No reply timeout (ms)" \
"\n -z <timeout> Dup timeout (ms)" \
"\n -A <string> Atlas measurement ID" \
+ "\n -D <size> Add IPv6 Destination Option this size" \
+ "\n -H <size> Add IPv6 Hop-by-hop Option this size" \
"\n -O <file> Name of output file" \
"\n -S <size> Size of packet" \
@@ -3569,11 +3571,11 @@
#define rpm2cpio_full_usage "\n\n" \
"Output a cpio archive of the rpm file"
-#define rptra6_trivial_usage \
+#define rptaddrs_trivial_usage \
-#define rptaddr6_full_usage "\n\n" \
+#define rptaddrs_full_usage "\n\n" \
-#define rptaddr6_trivial_usage \
+#define rptra6_trivial_usage \
#define rptra6_full_usage "\n\n" \
diff --git a/libbb/Kbuild b/libbb/Kbuild
index 178347d..0b77f72 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -10,6 +10,7 @@ lib-y += appletlib.o
lib-y += ask_confirmation.o
lib-y += atlas_bb64.o
lib-y += atlas_probe.o
+lib-y += atlas_timesync.o
lib-y += bb_askpass.o
lib-y += bb_basename.o
lib-y += bb_do_delay.o
@@ -17,6 +18,7 @@ lib-y += bb_pwd.o
lib-y += bb_qsort.o
lib-y += bb_strtod.o
lib-y += bb_strtonum.o
+lib-y += bind_interface.o
lib-y += change_identity.o
lib-y += chomp.o
lib-y += compare_string_array.o
diff --git a/libbb/atlas_timesync.c b/libbb/atlas_timesync.c
new file mode 100644
index 0000000..3434493
--- /dev/null
+++ b/libbb/atlas_timesync.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 RIPE NCC <atlas@ripe.net>
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+int get_timesync(void)
+{
+ FILE *fh;
+ int lastsync;
+
+ fh= fopen(ATLAS_TIMESYNC_FILE, "r");
+ if (!fh)
+ return -1;
+ fscanf(fh, "%d", &lastsync);
+ fclose(fh);
+ return time(NULL)-lastsync;
+}
+
diff --git a/libbb/bind_interface.c b/libbb/bind_interface.c
new file mode 100644
index 0000000..1eb4414
--- /dev/null
+++ b/libbb/bind_interface.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 RIPE NCC <atlas@ripe.net>
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+int bind_interface(int socket, int af, char *name)
+{
+ struct sockaddr_storage sa;
+
+ memset(&sa, '\0', sizeof(sa));
+
+ if (af == AF_INET)
+ {
+ sa.ss_family= AF_INET;
+ if (inet_pton(af, name,
+ &((struct sockaddr_in *)&sa)->sin_addr) == 1)
+ {
+ return bind(socket, (struct sockaddr *)&sa,
+ sizeof(sa));
+ }
+ }
+ else
+ {
+ sa.ss_family= AF_INET6;
+ if (inet_pton(af, name,
+ &((struct sockaddr_in6 *)&sa)->sin6_addr) == 1)
+ {
+ return bind(socket, (struct sockaddr *)&sa,
+ sizeof(sa));
+ }
+ }
+ if (setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, name,
+ strlen(name)+1) == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/networking/Config.in b/networking/Config.in
index cdf067a..84c89ad 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -705,11 +705,11 @@ config RPTRA6
help
Report received IPv6 router advertisements
-config RPTADDR6
- bool "rptaddr6"
+config RPTADDRS
+ bool "rptaddrs"
default n
help
- Report IPv6 addresses and routes
+ Report addresses, routes, dns both static and dynamic
config RXTXRPT
bool "rxtxrpt"
diff --git a/networking/Kbuild b/networking/Kbuild
index ddb143a..d550ed4 100644
--- a/networking/Kbuild
+++ b/networking/Kbuild
@@ -32,7 +32,7 @@ lib-$(CONFIG_PING6) += ping.o
lib-$(CONFIG_PSCAN) += pscan.o
lib-$(CONFIG_ROUTE) += route.o
lib-$(CONFIG_RPTRA6) += rptra6.o
-lib-$(CONFIG_RPTADDR6) += rptaddr6.o
+lib-$(CONFIG_RPTADDRS) += rptaddrs.o
lib-$(CONFIG_RXTXRPT) += rxtxrpt.o
lib-$(CONFIG_SLATTACH) += slattach.o
lib-$(CONFIG_SSLGETCERT) += sslgetcert.o
diff --git a/networking/atlasinit.c b/networking/atlasinit.c
new file mode 100644
index 0000000..121b508
--- /dev/null
+++ b/networking/atlasinit.c
@@ -0,0 +1,740 @@
+/* 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/rptaddrs.c b/networking/rptaddrs.c
new file mode 100644
index 0000000..1115559
--- /dev/null
+++ b/networking/rptaddrs.c
@@ -0,0 +1,775 @@
+/*
+ * rptaddrs.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 <resolv.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <inet_common.h>
+#include "../eperd/eperd.h"
+#include "../eperd/readresolv.h"
+
+#include "libbb.h"
+
+#define IPV4_ROUTE_FILE "/proc/net/route"
+#define IF_INET6_FILE "/proc/net/if_inet6"
+#define IPV6_ROUTE_FILE "/proc/net/ipv6_route"
+#define SUFFIX ".new"
+
+#define IPV4_STATIC ATLAS_STATUS "/network_v4_static_info.json"
+#define IPV6_STATIC ATLAS_STATUS "/network_v6_static_info.json"
+#define DNS_STATIC ATLAS_STATUS "/network_dns_static_info.json"
+#define NETWORK_INFO ATLAS_STATUS "/network_info.txt"
+
+#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 FILE *setup_cache(char *cache_name);
+static int setup_ipv4_rpt(FILE *of);
+static int setup_dhcpv4(FILE *of);
+static int setup_ipv6_rpt(FILE *of);
+static int setup_dns(FILE *of);
+static int setup_static_rpt(FILE *of);
+static int report_line(FILE *of, const char *fn);
+static int check_cache(char *cache_name);
+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 rptaddrs_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;
+ FILE *cf;
+
+ 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_N))
+ {
+ crondlog(LVL8 "insecure file '%s' : allowed '%s'", out_name,
+ SAFE_PREFIX_N);
+ 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;
+
+ cf= setup_cache(cache_name);
+ if (cf == NULL)
+ return 1;
+
+ r= setup_ipv4_rpt(cf);
+ if (r == -1)
+ {
+ fclose(cf);
+ return 1;
+ }
+
+ r= setup_dhcpv4(cf);
+ if (r == -1)
+ {
+ fclose(cf);
+ return 1;
+ }
+
+ r= setup_ipv6_rpt(cf);
+ if (r == -1)
+ {
+ fclose(cf);
+ return 1;
+ }
+
+ r= setup_dns(cf);
+ if (r == -1)
+ {
+ fclose(cf);
+ return 1;
+ }
+
+ r= setup_static_rpt(cf);
+ if (r == -1)
+ {
+ fclose(cf);
+ return 1;
+ }
+ fclose(cf);
+
+ need_report= check_cache(cache_name);
+ if (need_report)
+ {
+ r = rpt_ipv6(cache_name, out_name, opt_atlas, opt_append);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static FILE *setup_cache(char *cache_name)
+{
+ FILE *out_file;
+ char filename[80];
+
+ if (strlen(cache_name) + strlen(SUFFIX) + 1 > sizeof(filename))
+ {
+ report("cache name '%s' too long", cache_name);
+ return NULL;
+ }
+
+ 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 NULL;
+ }
+
+ return out_file;
+}
+
+#define MAX_INF 10
+
+static int setup_ipv4_rpt(FILE *of)
+{
+ int i, r, s, first;
+ unsigned dest, gateway, flags, refcnt, use, metric, mask;
+ FILE *in_file;
+ struct in_addr in_addr;
+ struct ifconf ifconf;
+ struct ifreq ifreq1;
+ struct ifreq ifreq[MAX_INF];
+ char infname[20];
+ char line[256];
+
+ s= socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (s == -1)
+ {
+ report_err("socket failed");
+ return -1;
+ }
+ ifconf.ifc_len= sizeof(ifreq);
+ ifconf.ifc_req= ifreq;
+ r= ioctl(s, SIOCGIFCONF, &ifconf);
+ if (r == -1)
+ {
+ report_err("SIOCGIFCONF failed");
+ close(s);
+ return -1;
+ }
+
+ fprintf(of, DBQ(inet-addresses) ": [ ");
+ for (i= 0; i<ifconf.ifc_len/sizeof(ifreq[0]); i++)
+ {
+ memcpy(ifreq1.ifr_name, ifreq[i].ifr_name,
+ sizeof(ifreq1.ifr_name));
+ r= ioctl(s, SIOCGIFNETMASK, &ifreq1);
+ if (r == -1)
+ {
+ report_err("SIOCGIFNETMASK failed");
+ close(s);
+ return -1;
+ }
+ fprintf(of, "%s{ " DBQ(inet-addr) ": " DBQ(%s) ", ",
+ i == 0 ? "" : ", ",
+ inet_ntoa(((struct sockaddr_in *)(&ifreq[i].ifr_addr))
+ ->sin_addr));
+ fprintf(of, DBQ(netmask) ": " DBQ(%s) ", "
+ DBQ(interface) ": " DBQ(%s) " }",
+ inet_ntoa(((struct sockaddr_in *)(&ifreq1.ifr_addr))->
+ sin_addr),
+ ifreq[i].ifr_name);
+ }
+
+ close(s);
+
+ fprintf(of, " ]");
+
+ in_file= fopen(IPV4_ROUTE_FILE, "r");
+ if (in_file == NULL)
+ {
+ report_err("unable to open '%s'", IPV4_ROUTE_FILE);
+ return -1;
+ }
+
+ /* Skip first line */
+ fgets(line, sizeof(line), in_file);
+
+ fprintf(of, ", " DBQ(inet-routes) ": [ ");
+ first= 1;
+
+ while (fgets(line, sizeof(line), in_file) != NULL)
+ {
+ sscanf(line, "%16s %x %x %x %d %d %d %x",
+ infname, &dest, &gateway, &flags, &refcnt, &use,
+ &metric, &mask);
+ in_addr.s_addr= dest;
+ fprintf(of, "%s{ " DBQ(destination) ": " DBQ(%s) ", ",
+ first ? "" : ", ", inet_ntoa(in_addr));
+ in_addr.s_addr= mask;
+ fprintf(of, DBQ(netmask) ": " DBQ(%s) ", ",
+ inet_ntoa(in_addr));
+ in_addr.s_addr= gateway;
+ fprintf(of, DBQ(next-hop) ": " DBQ(%s) ", "
+ DBQ(interface) ": " DBQ(%s) " }",
+ inet_ntoa(in_addr), infname);
+ first= 0;
+ }
+
+ fprintf(of, " ]");
+
+ fclose(in_file);
+
+ return 0;
+}
+
+static int setup_dhcpv4(FILE *of)
+{
+ int found;
+ FILE *in_file;
+ char *value;
+ char line[128];
+
+ in_file= fopen(NETWORK_INFO, "r");
+ if (in_file == NULL)
+ {
+ report_err("unable to open '%s'", NETWORK_INFO);
+ return -1;
+ }
+ found= 0;
+ while (fgets(line, sizeof(line), in_file) != NULL)
+ {
+ if (strncmp(line, "DHCP ", 5) == 0)
+ {
+ value= NULL;
+ if (strncmp(line+5, "True", 4) == 0)
+ value= "true";
+ else if (strncmp(line+5, "False", 5) == 0)
+ value= "false";
+ if (value)
+ {
+ fprintf(of, ", " DBQ(inet-dhcp) ": %s",
+ value);
+ found= 1;
+ break;
+ }
+ }
+ }
+
+ fclose(in_file);
+ if (found)
+ return 0;
+ report("setup_dhcpv4: DHCP field not found");
+ return -1;
+}
+
+static int setup_ipv6_rpt(FILE *of)
+{
+ int r, n;
+ 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 buf2[1024];
+
+ FILE *in_file;
+
+ /* Copy IF_INET6_FILE */
+ in_file= fopen(IF_INET6_FILE, "r");
+ if (in_file == NULL)
+ {
+ report_err("unable to open '%s'", IF_INET6_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, of) != r)
+ {
+ report_err("error writing to '%s'", filename);
+ fclose(in_file);
+ return -1;
+ }
+
+ if (ferror(in_file))
+ {
+ report_err("error reading from '%s'", IF_INET6_FILE);
+ fclose(in_file);
+ return -1;
+ }
+ }
+ if ( n > 0 ) {
+ r = snprintf(buf2, 2, "]");
+ }
+ if (fwrite(buf2, 1, r, of) != r)
+ {
+ report_err("error writing to '%s'", filename);
+ fclose(in_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);
+ 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);
+ 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, of) != r)
+ {
+ report_err("error writing to '%s'", filename);
+ fclose(in_file);
+ return -1;
+ }
+ n++;
+ }
+ if ( n > 0 ) {
+ r = snprintf(buf2, 2, "]");
+ }
+ if (fwrite(buf2, 1, r, of) != r)
+ {
+ report_err("error writing to '%s'", filename);
+ fclose(in_file);
+ return -1;
+ }
+
+
+ if (ferror(in_file))
+ {
+ report_err("error reading from '%s'", IPV6_ROUTE_FILE);
+ fclose(in_file);
+ return -1;
+ }
+ fclose(in_file);
+
+ return 0;
+}
+
+static int setup_dns(FILE *of)
+{
+ int i, resolv_max;
+ char nslist[MAXNS][INET6_ADDRSTRLEN * 2];
+
+ resolv_max= 0;
+
+ get_local_resolvers_nocache(nslist, &resolv_max);
+
+ fprintf(of, ", " DBQ(dns) ": [ ");
+ for (i= 0; i<resolv_max; i++)
+ {
+ fprintf(of, "%s{ " DBQ(nameserver) ": " DBQ(%s) " }",
+ i == 0 ? "" : ", ",
+ nslist[i]);
+ }
+
+ fprintf(of, " ]");
+
+ return 0;
+}
+
+static int setup_static_rpt(FILE *of)
+{
+ int r;
+
+ r= report_line(of, IPV4_STATIC);
+ if (r == -1)
+ return -1;
+ r= report_line(of, IPV6_STATIC);
+ if (r == -1)
+ return -1;
+ r= report_line(of, DNS_STATIC);
+ if (r == -1)
+ return -1;
+ return 0;
+}
+
+static int report_line(FILE *of, const char *fn)
+{
+ FILE *f;
+ char *nl;
+ char line[256];
+
+ f= fopen(fn, "r");
+ if (f == NULL)
+ {
+ if (errno != ENOENT)
+ {
+ report_err("open '%s' failed", fn);
+ return -1;
+ }
+ }
+ else
+ {
+ if (fgets(line, sizeof(line), f) == NULL)
+ {
+ if (ferror(f))
+ {
+ report_err("error reading from '%s'", fn);
+ }
+ else
+ report("error reading from '%s': EOF");
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ nl= strchr(line, '\n');
+ if (nl == NULL)
+ {
+ report("line too long in '%s'", fn);
+ return -1;
+ }
+ *nl= '\0';
+ fprintf(of, ", %s", line);
+ }
+
+ return 0;
+}
+
+static int check_cache(char *cache_name)
+{
+ int r, need_report;
+ char filename[80];
+
+ char buf1[1024];
+ char buf2[1024];
+ FILE *in_file, *cache_file;
+
+ strlcpy(filename, cache_name, sizeof(filename));
+ strlcat(filename, SUFFIX, sizeof(filename));
+
+ need_report= 0;
+
+ /* Now check if the new file is different from the cache one */
+ 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 0;
+ }
+ }
+ else
+ {
+ if (unlink(filename) == -1)
+ {
+ report_err("unlinking '%s' failed",
+ filename);
+ }
+ }
+
+ return need_report;
+}
+
+static int rpt_ipv6(char *cache_name, char *out_name, char *opt_atlas, int opt_append)
+{
+ FILE *file;
+ FILE *fh;
+ 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, "a");
+ else
+ fh= fopen(out_name, "w");
+
+ if (!fh)
+ {
+ report_err("unable to append to '%s'", out_name);
+ return 1;
+ }
+ }
+ 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, "rptaddrs: ");
+ 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, "rptaddrs: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": %s\n", strerror(t_errno));
+
+ va_end(ap);
+}
diff --git a/networking/rptra6.c b/networking/rptra6.c
index 8b45e72..b481252 100644
--- a/networking/rptra6.c
+++ b/networking/rptra6.c
@@ -35,7 +35,7 @@ static void usage(void)
exit(1);
}
-int rptaddr6_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
+int rptra6_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
int rptra6_main(int argc, char *argv[])
{
int i, r, first, sock, on, nrecv, rcvd_ttl, olen;
diff --git a/shell/hush.c b/shell/hush.c
index 13aceb3..10cab48 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -770,7 +770,7 @@ static int builtin_epoch(char **argv);
static int builtin_condmv(char **argv);
static int builtin_dfrm(char **argv);
static int builtin_rxtxrpt(char **argv);
-static int builtin_rptaddr6(char **argv);
+static int builtin_rptaddrs(char **argv);
static int builtin_true(char **argv);
static int builtin_set(char **argv);
static int builtin_shift(char **argv);
@@ -830,7 +830,7 @@ static const struct built_in_command bltins[] = {
BLTIN("condmv" , builtin_condmv, "conditional move"),
BLTIN("dfrm" , builtin_dfrm, "cleanup if free space gets too low"),
BLTIN("rxtxrpt" , builtin_rxtxrpt, "report RX and TX"),
- BLTIN("rptaddr6" , builtin_rptaddr6, "report ipv6 address(es) and route(s)"),
+ BLTIN("rptaddrs" , builtin_rptaddrs, "report address(es), route(s), and dns"),
BLTIN("echo" , builtin_echo, "Write to stdout"),
BLTIN("eval" , builtin_eval, "Construct and run shell command"),
BLTIN("exec" , builtin_exec, "Execute command, don't return to shell"),
@@ -4682,15 +4682,15 @@ static int builtin_rxtxrpt(char **argv)
return rxtxrpt_main(argc, argv);
}
-int builitin_rptaddr6(int argc, char *argv[]);
+int builitin_rptaddrs(int argc, char *argv[]);
-static int builtin_rptaddr6(char **argv)
+static int builtin_rptaddrs(char **argv)
{
int argc;
for (argc= 0; argv[argc] != 0; argc++)
;
- return rptaddr6_main(argc, argv);
+ return rptaddrs_main(argc, argv);
}