#if defined(__APPLE__) #include #endif #include #include #include #include #include #include #include #include #include #if defined(DMALLOC) #include #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 \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; ihop_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; ipattern_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; iping_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; }