aboutsummaryrefslogtreecommitdiff
path: root/eperd
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 /eperd
parentb1b227fa5e00d08af047ab9a012211b66c6b0f13 (diff)
ripe-atlas-fw: imported version 46504650
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Diffstat (limited to 'eperd')
-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
10 files changed, 656 insertions, 512 deletions
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;