#if defined(__APPLE__)
#include <stdint.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#if defined(DMALLOC)
#include <dmalloc.h>
#endif
#include "scamper_addr.h"
#include "scamper_list.h"
#include "scamper_tlv.h"
#include "scamper_trace.h"
#include "scamper_ping.h"
#include "scamper_file.h"
static void usage()
{
fprintf(stderr, "usage: warts-dump <file>\n");
return;
}
static void dump_list_summary(scamper_list_t *list)
{
if(list != NULL)
{
fprintf(stdout, " list id: %d", list->id);
if(list->name != NULL)
fprintf(stdout, ", name: %s", list->name);
if(list->monitor != NULL)
fprintf(stdout, ", monitor: %s", list->monitor);
fprintf(stdout, "\n");
}
return;
}
static void dump_cycle_summary(scamper_cycle_t *cycle)
{
if(cycle != NULL)
{
fprintf(stdout, " cycle id: %d\n", cycle->id);
}
return;
}
static void dump_start(struct timeval *start)
{
time_t tt = start->tv_sec;
char buf[32];
memcpy(buf, ctime(&tt), 24); buf[24] = '\0';
fprintf(stdout, " start: %s %06d\n", buf, (int)start->tv_usec);
return;
}
static void dump_trace_hop(scamper_trace_hop_t *hop)
{
scamper_tlv_t *tlv;
char addr[256];
fprintf(stdout, "hop %2d %s\n",
hop->hop_probe_ttl,
scamper_addr_tostr(hop->hop_addr, addr, sizeof(addr)));
fprintf(stdout, " attempt: %d, rtt: %d.%06d sec\n",
hop->hop_probe_id,
(int)hop->hop_rtt.tv_sec, (int)hop->hop_rtt.tv_usec);
fprintf(stdout, " probe_size: %d", hop->hop_probe_size);
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_REPLY_TTL)
{
fprintf(stdout, ", reply_ttl: %d", hop->hop_reply_ttl);
}
fprintf(stdout, "\n");
if((hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TCP) == 0)
{
fprintf(stdout, " icmp type: %d, code: %d\n",
hop->hop_icmp_type, hop->hop_icmp_code);
}
else
{
fprintf(stdout, " tcp flags: 0x%02x", hop->hop_tcp_flags);
if(hop->hop_tcp_flags != 0)
{
fprintf(stdout, " (%s%s%s%s%s%s%s%s )",
(hop->hop_tcp_flags & 0x01) ? " fin" : "",
(hop->hop_tcp_flags & 0x02) ? " syn" : "",
(hop->hop_tcp_flags & 0x04) ? " rst" : "",
(hop->hop_tcp_flags & 0x08) ? " psh" : "",
(hop->hop_tcp_flags & 0x10) ? " ack" : "",
(hop->hop_tcp_flags & 0x20) ? " urg" : "",
(hop->hop_tcp_flags & 0x40) ? " ece" : "",
(hop->hop_tcp_flags & 0x80) ? " cwr" : "");
}
fprintf(stdout, "\n");
}
fprintf(stdout, " flags: 0x%02x", hop->hop_flags);
if(hop->hop_flags != 0)
{
fprintf(stdout, " (");
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_SOCK_RX)
fprintf(stdout, " sockrxts");
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_TX)
fprintf(stdout, " dltxts");
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_RX)
fprintf(stdout, " dlrxts");
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_TSC)
fprintf(stdout, " tscrtt");
if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_REPLY_TTL)
fprintf(stdout, " replyttl");
fprintf(stdout, " )");
}
fprintf(stdout, "\n");
if(hop->hop_tlvs != NULL)
{
for(tlv = hop->hop_tlvs; tlv != NULL; tlv = tlv->tlv_next)
{
switch(tlv->tlv_type)
{
case SCAMPER_TRACE_HOP_TLV_REPLY_IPID:
fprintf(stdout, " ipid outer 0x%04x", tlv->tlv_val_16);
break;
case SCAMPER_TRACE_HOP_TLV_REPLY_IPTOS:
fprintf(stdout, " iptos outer 0x%02x", tlv->tlv_val_8);
break;
case SCAMPER_TRACE_HOP_TLV_NHMTU:
fprintf(stdout, " nhmtu %d", tlv->tlv_val_16);
break;
case SCAMPER_TRACE_HOP_TLV_INNER_IPTTL:
fprintf(stdout, " turn ttl %d", tlv->tlv_val_8);
break;
case SCAMPER_TRACE_HOP_TLV_INNER_IPLEN:
fprintf(stdout, " iplen inner %d", tlv->tlv_val_16);
break;
}
}
fprintf(stdout, "\n");
}
return;
}
static void dump_trace(scamper_trace_t *trace)
{
scamper_trace_hop_t *hop;
uint16_t i;
char buf[256];
scamper_addr_tostr(trace->src, buf, sizeof(buf));
fprintf(stdout, "traceroute from %s to ", buf);
scamper_addr_tostr(trace->dst, buf, sizeof(buf));
fprintf(stdout, "%s\n", buf);
dump_list_summary(trace->list);
dump_cycle_summary(trace->cycle);
dump_start(&trace->start);
fprintf(stdout, " type: ");
switch(trace->type)
{
case SCAMPER_TRACE_TYPE_ICMP_ECHO:
fprintf(stdout, "icmp, echo id: %d", trace->sport);
break;
case SCAMPER_TRACE_TYPE_ICMP_ECHO_PARIS:
fprintf(stdout, "icmp paris, echo id: %d", trace->sport);
break;
case SCAMPER_TRACE_TYPE_UDP:
fprintf(stdout, "udp, sport: %d, base dport %d",
trace->sport, trace->dport);
break;
case SCAMPER_TRACE_TYPE_UDP_PARIS:
fprintf(stdout, "udp paris, sport: %d, dport %d",
trace->sport, trace->dport);
break;
case SCAMPER_TRACE_TYPE_TCP:
fprintf(stdout, "tcp, sport: %d, dport %d", trace->sport, trace->dport);
break;
default:
fprintf(stdout, "%d", trace->type);
break;
}
fprintf(stdout, "\n");
fprintf(stdout, " attempts: %d, hoplimit: %d, loops: %d\n",
trace->attempts, trace->hoplimit, trace->loops);
fprintf(stdout, " flags: 0x%02x", trace->flags);
if(trace->flags != 0)
{
fprintf(stdout, " (");
if(trace->flags & SCAMPER_TRACE_FLAG_ALLATTEMPTS)
fprintf(stdout, " all_attempts");
if(trace->flags & SCAMPER_TRACE_FLAG_PMTUD)
fprintf(stdout, " pmtud");
if(trace->flags & SCAMPER_TRACE_FLAG_DL)
fprintf(stdout, " dltxts");
fprintf(stdout, ")");
}
fprintf(stdout, "\n");
fprintf(stdout, " stop reason: ");
switch(trace->stop_reason)
{
case SCAMPER_TRACE_STOP_NONE:
fprintf(stdout, "none");
break;
case SCAMPER_TRACE_STOP_COMPLETED:
fprintf(stdout, "done");
break;
case SCAMPER_TRACE_STOP_UNREACH:
fprintf(stdout, "icmp unreach %d", trace->stop_data);
break;
case SCAMPER_TRACE_STOP_ICMP:
fprintf(stdout, "icmp type %d", trace->stop_data);
break;
case SCAMPER_TRACE_STOP_LOOP:
fprintf(stdout, "loop %d", trace->stop_data);
break;
case SCAMPER_TRACE_STOP_DEAD:
fprintf(stdout, "dead %d", trace->stop_data);
break;
case SCAMPER_TRACE_STOP_ERROR:
fprintf(stdout, "sendto errno %d", trace->stop_data);
break;
case SCAMPER_TRACE_STOP_HOPLIMIT:
fprintf(stdout, "hoplimit");
break;
default:
fprintf(stdout, "reason 0x%02x data 0x%02x",
trace->stop_reason, trace->stop_data);
break;
}
fprintf(stdout, "\n");
for(i=0; i<trace->hop_count; i++)
{
for(hop = trace->hops[i]; hop != NULL; hop = hop->hop_next)
{
dump_trace_hop(hop);
}
}
if(trace->pmtud != NULL)
{
fprintf(stdout, "pmtud: ifmtu %d, pmtu %d\n",
trace->pmtud->ifmtu, trace->pmtud->pmtu);
for(hop = trace->pmtud->hops; hop != NULL; hop = hop->hop_next)
{
dump_trace_hop(hop);
}
}
fprintf(stdout, "\n");
scamper_trace_free(trace);
return;
}
static void dump_ping_reply(scamper_ping_reply_t *reply)
{
char addr[256];
fprintf(stdout, "reply from %s, attempt: %d, rtt: %d.%06d sec\n",
scamper_addr_tostr(reply->addr, addr, sizeof(addr)),
reply->probe_id+1, (int)reply->rtt.tv_sec, (int)reply->rtt.tv_usec);
fprintf(stdout, " size: %d", reply->reply_size);
if(reply->flags & SCAMPER_PING_REPLY_FLAG_REPLY_TTL)
{
fprintf(stdout, ", ttl %d", reply->reply_ttl);
}
fprintf(stdout, "\n");
fprintf(stdout, " icmp type: %d, code: %d\n",
reply->icmp_type, reply->icmp_code);
return;
}
static void dump_ping(scamper_ping_t *ping)
{
scamper_ping_reply_t *reply;
char buf[256];
int i;
scamper_addr_tostr(ping->src, buf, sizeof(buf));
fprintf(stdout, "ping from %s to ", buf);
scamper_addr_tostr(ping->dst, buf, sizeof(buf));
fprintf(stdout, "%s\n", buf);
dump_list_summary(ping->list);
dump_cycle_summary(ping->cycle);
dump_start(&ping->start);
fprintf(stdout, " probe count: %d, size: %d, wait: %d, ttl %d\n",
ping->probe_count,ping->probe_size,ping->probe_wait,ping->probe_ttl);
fprintf(stdout, " probes sent: %d", ping->ping_sent);
if(ping->reply_count > 0)
{
fprintf(stdout, ", replies requested: %d", ping->reply_count);
}
fprintf(stdout, "\n");
/* dump pad bytes, if used */
if(ping->pattern_len > 0 && ping->pattern_bytes != NULL)
{
fprintf(stdout, " pattern bytes (%d): ", ping->pattern_len);
for(i=0; i<ping->pattern_len; i++)
{
fprintf(stdout, "%02x", ping->pattern_bytes[i]);
}
fprintf(stdout, "\n");
}
fprintf(stdout, " stop reason: ");
switch(ping->stop_reason)
{
case SCAMPER_PING_STOP_NONE:
fprintf(stdout, "none"); break;
case SCAMPER_PING_STOP_COMPLETED:
fprintf(stdout, "done"); break;
case SCAMPER_PING_STOP_ERROR:
fprintf(stdout, "sendto errno %d", ping->stop_data); break;
default:
fprintf(stdout, "reason 0x%02x data 0x%02x",
ping->stop_reason, ping->stop_data);
break;
}
fprintf(stdout, "\n");
for(i=0; i<ping->ping_sent; i++)
{
for(reply = ping->ping_replies[i]; reply != NULL; reply = reply->next)
{
dump_ping_reply(reply);
}
}
fprintf(stdout, "\n");
scamper_ping_free(ping);
return;
}
static void dump_cycle(scamper_cycle_t *cycle, const char *type)
{
time_t tt;
char buf[32];
if(strcmp(type, "start") == 0 || strcmp(type, "def") == 0)
{
tt = cycle->start_time;
}
else
{
tt = cycle->stop_time;
}
memcpy(buf, ctime(&tt), 24); buf[24] = '\0';
printf("cycle %s, list %s %d, cycle %d, time %s\n",
type, cycle->list->name, cycle->list->id, cycle->id, buf);
scamper_cycle_free(cycle);
return;
}
static void dump_list(scamper_list_t *list)
{
printf("list id %d, name %s", list->id, list->name);
if(list->descr != NULL) printf(", descr \"%s\"", list->descr);
printf("\n");
scamper_list_free(list);
return;
}
static void dump_addr(scamper_addr_t *addr)
{
char buf[128];
printf("addr %s\n", scamper_addr_tostr(addr, buf, sizeof(buf)));
scamper_addr_free(addr);
return;
}
int main(int argc, char *argv[])
{
scamper_file_t *file;
scamper_file_filter_t *filter;
uint16_t filter_types[] = {
SCAMPER_FILE_OBJ_LIST,
SCAMPER_FILE_OBJ_CYCLE_START,
SCAMPER_FILE_OBJ_CYCLE_DEF,
SCAMPER_FILE_OBJ_CYCLE_STOP,
SCAMPER_FILE_OBJ_TRACE,
SCAMPER_FILE_OBJ_PING,
};
uint16_t filter_cnt = sizeof(filter_types)/sizeof(uint16_t);
void *data;
uint16_t type;
#if defined(DMALLOC)
free(malloc(1));
#endif
if(argc == 1)
{
if((file = scamper_file_openfd(STDIN_FILENO, "-", 'r', "warts")) == NULL)
{
usage();
fprintf(stderr, "could not use stdin\n");
return -1;
}
}
else if(argc == 2)
{
if((file = scamper_file_open(argv[1], 'r', NULL)) == NULL)
{
usage();
fprintf(stderr, "could not open %s\n", argv[1]);
return -1;
}
}
else
{
usage();
return -1;
}
if((filter = scamper_file_filter_alloc(filter_types, filter_cnt)) == NULL)
{
usage();
fprintf(stderr, "could not alloc fitler\n");
return -1;
}
while(scamper_file_read(file, filter, &type, &data) == 0)
{
/* hit eof */
if(data == NULL)
{
goto done;
}
switch(type)
{
case SCAMPER_FILE_OBJ_ADDR:
dump_addr(data);
break;
case SCAMPER_FILE_OBJ_TRACE:
dump_trace(data);
break;
case SCAMPER_FILE_OBJ_PING:
dump_ping(data);
break;
case SCAMPER_FILE_OBJ_LIST:
dump_list(data);
break;
case SCAMPER_FILE_OBJ_CYCLE_START:
dump_cycle(data, "start");
break;
case SCAMPER_FILE_OBJ_CYCLE_STOP:
dump_cycle(data, "stop");
break;
case SCAMPER_FILE_OBJ_CYCLE_DEF:
dump_cycle(data, "def");
break;
}
}
scamper_file_filter_free(filter);
scamper_file_close(file);
fprintf(stderr, "error encountered\n");
return -1;
done:
scamper_file_filter_free(filter);
scamper_file_close(file);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1