int scamper_addr2mac_add(int ifindex, scamper_addr_t *ip, scamper_addr_t *mac) { addr2mac_t *a2m = NULL; char ipstr[128], macstr[128]; if(scamper_addr2mac_whohas(ifindex, ip) != NULL) return 0; if((a2m = addr2mac_alloc(ifindex, ip, mac, 0)) == NULL) return -1; if(splaytree_insert(tree, a2m) == NULL) { printerror(errno, strerror, __func__, "could not add %s:%s to tree", scamper_addr_tostr(a2m->ip, ipstr, sizeof(ipstr)), scamper_addr_tostr(a2m->mac, macstr, sizeof(macstr))); addr2mac_free(a2m); return -1; } scamper_debug(__func__, "ifindex %d ip %s mac %s", ifindex, scamper_addr_tostr(a2m->ip, ipstr, sizeof(ipstr)), scamper_addr_tostr(a2m->mac, macstr, sizeof(macstr))); return 0; }
static char *ping_header(const scamper_ping_t *ping) { char header[192], src[64], dst[64]; snprintf(header, sizeof(header), "ping %s to %s: %d byte packets\n", scamper_addr_tostr(ping->src, src, sizeof(src)), scamper_addr_tostr(ping->dst, dst, sizeof(dst)), ping->probe_size); return strdup(header); }
static int addr2mac_add(const int ifindex, const int type, const void *ipraw, const void *macraw, const time_t expire) { const int mt = SCAMPER_ADDR_TYPE_ETHERNET; scamper_addr_t *mac = NULL; scamper_addr_t *ip = NULL; addr2mac_t *addr2mac = NULL; char ipstr[128], macstr[128]; if((ip = scamper_addrcache_get(addrcache, type, ipraw)) == NULL) { printerror(errno, strerror, __func__, "could not get ip"); goto err; } if((mac = scamper_addrcache_get(addrcache, mt, macraw)) == NULL) { printerror(errno, strerror, __func__, "could not get mac"); goto err; } if((addr2mac = addr2mac_alloc(ifindex, ip, mac, expire)) == NULL) { goto err; } scamper_addr_free(ip); ip = NULL; scamper_addr_free(mac); mac = NULL; if(splaytree_insert(tree, addr2mac) == NULL) { printerror(errno, strerror, __func__, "could not add %s:%s to tree", scamper_addr_tostr(addr2mac->ip, ipstr, sizeof(ipstr)), scamper_addr_tostr(addr2mac->mac, macstr, sizeof(macstr))); goto err; } scamper_debug(__func__, "ifindex %d ip %s mac %s expire %d", ifindex, scamper_addr_tostr(addr2mac->ip, ipstr, sizeof(ipstr)), scamper_addr_tostr(addr2mac->mac, macstr, sizeof(macstr)), expire); return 0; err: if(addr2mac != NULL) addr2mac_free(addr2mac); if(mac != NULL) scamper_addr_free(mac); if(ip != NULL) scamper_addr_free(ip); return -1; }
char *scamper_task_sig_tostr(scamper_task_sig_t *sig, char *buf, size_t len) { char tmp[64]; size_t off = 0; if(sig->sig_type == SCAMPER_TASK_SIG_TYPE_TX_IP) string_concat(buf, len, &off, "ip %s", scamper_addr_tostr(sig->sig_tx_ip_dst, tmp, sizeof(tmp))); else if(sig->sig_type == SCAMPER_TASK_SIG_TYPE_TX_ND) string_concat(buf, len, &off, "nd %s", scamper_addr_tostr(sig->sig_tx_nd_ip, tmp, sizeof(tmp))); else if(sig->sig_type == SCAMPER_TASK_SIG_TYPE_SNIFF) string_concat(buf, len, &off, "sniff %s icmp-id %04x", scamper_addr_tostr(sig->sig_sniff_src, tmp, sizeof(tmp)), sig->sig_sniff_icmp_id); else return NULL; return buf; }
int scamper_file_text_sting_write(const scamper_file_t *sf, const scamper_sting_t *sting) { int fd = scamper_file_getfd(sf); char buf[192], src[64], dst[64]; size_t len; uint32_t i, txc = 0; snprintf(buf, sizeof(buf), "sting from %s:%d to %s:%d, %d probes, %dms mean\n" " data-ack count %d, holec %d\n", scamper_addr_tostr(sting->src, src, sizeof(src)), sting->sport, scamper_addr_tostr(sting->dst, dst, sizeof(dst)), sting->dport, sting->count, sting->mean, sting->dataackc, sting->holec); len = strlen(buf); write_wrap(fd, buf, NULL, len); if(sting->holec > 0) { for(i=0; i<sting->pktc; i++) { if((sting->pkts[i]->flags & SCAMPER_STING_PKT_FLAG_DATA) == 0) continue; txc++; if(sting->pkts[i]->flags & SCAMPER_STING_PKT_FLAG_HOLE) { snprintf(buf, sizeof(buf), " probe %d hole\n", txc); len = strlen(buf); write_wrap(fd, buf, NULL, len); } } } return 0; }
static char *ping_stats(const scamper_ping_t *ping) { scamper_ping_stats_t stats; size_t off = 0; char str[64]; char buf[512]; int rp = 0; if(scamper_ping_stats(ping, &stats) != 0) return NULL; if(ping->ping_sent != 0) rp = ((ping->ping_sent - stats.nreplies) * 100) / ping->ping_sent; string_concat(buf, sizeof(buf), &off, "--- %s ping statistics ---\n", scamper_addr_tostr(ping->dst, str, sizeof(str))); string_concat(buf, sizeof(buf), &off, "%d packets transmitted, %d packets received, ", ping->ping_sent, stats.nreplies); if(stats.ndups > 0) string_concat(buf, sizeof(buf), &off, "+%d duplicates, ", stats.ndups); string_concat(buf, sizeof(buf), &off, "%d%% packet loss\n", rp); if(stats.nreplies > 0) { string_concat(buf, sizeof(buf), &off, "round-trip min/avg/max/stddev ="); string_concat(buf, sizeof(buf), &off, " %s", timeval_tostr(&stats.min_rtt, str, sizeof(str))); string_concat(buf, sizeof(buf), &off, "/%s", timeval_tostr(&stats.avg_rtt, str, sizeof(str))); string_concat(buf, sizeof(buf), &off, "/%s", timeval_tostr(&stats.max_rtt, str, sizeof(str))); string_concat(buf, sizeof(buf), &off, "/%s ms\n", timeval_tostr(&stats.stddev_rtt, str, sizeof(str))); } return strdup(buf); }
/* * scamper_getsrc * * given a destination address, determine the src address used in the IP * header to transmit probes to it. */ scamper_addr_t *scamper_getsrc(const scamper_addr_t *dst, int ifindex) { struct sockaddr_storage sas; scamper_addr_t *src; socklen_t socklen, sockleno; int sock; void *addr; char buf[64]; if(dst->type == SCAMPER_ADDR_TYPE_IPV4) { if(udp4 == -1 && (udp4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { printerror(errno, strerror, __func__, "could not open udp4 sock"); return NULL; } sock = udp4; addr = &((struct sockaddr_in *)&sas)->sin_addr; socklen = sizeof(struct sockaddr_in); sockaddr_compose((struct sockaddr *)&sas, AF_INET, dst->addr, 80); } else if(dst->type == SCAMPER_ADDR_TYPE_IPV6) { if(udp6 == -1 && (udp6 = socket(AF_INET6, SOCK_DGRAM,IPPROTO_UDP)) == -1) { printerror(errno, strerror, __func__, "could not open udp6 sock"); return NULL; } sock = udp6; addr = &((struct sockaddr_in6 *)&sas)->sin6_addr; socklen = sizeof(struct sockaddr_in6); sockaddr_compose((struct sockaddr *)&sas, AF_INET6, dst->addr, 80); if(scamper_addr_islinklocal(dst) != 0) { ((struct sockaddr_in6 *)&sas)->sin6_scope_id = ifindex; } } else return NULL; if(connect(sock, (struct sockaddr *)&sas, socklen) != 0) { printerror(errno, strerror, __func__, "connect to dst failed for %s", scamper_addr_tostr(dst, buf, sizeof(buf))); return NULL; } sockleno = socklen; if(getsockname(sock, (struct sockaddr *)&sas, &sockleno) != 0) { printerror(errno, strerror, __func__, "could not getsockname for %s", scamper_addr_tostr(dst, buf, sizeof(buf))); return NULL; } src = scamper_addrcache_get(addrcache, dst->type, addr); memset(&sas, 0, sizeof(sas)); connect(sock, (struct sockaddr *)&sas, socklen); return src; }
int main(int argc, char *argv[]) { scamper_file_t *file[2]; scamper_file_filter_t *filter; scamper_trace_t *trace; tracepair_t *pair, fm; uint16_t type = SCAMPER_FILE_OBJ_TRACE; char buf[256]; int i, filec_open; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); #endif if(check_options(argc, argv) != 0) goto err; if((filter = scamper_file_filter_alloc(&type, 1)) == NULL) { fprintf(stderr, "could not allocate filter\n"); goto err; } memset(file, 0, sizeof(file)); for(i=0; i<filec; i++) { if((file[i] = scamper_file_open(files[i], 'r', NULL)) == NULL) { fprintf(stderr, "could not open %s\n", files[i]); goto err; } } filec_open = filec; if((pairs = splaytree_alloc(tracepair_cmp)) == NULL) { fprintf(stderr, "could not alloc tracepair tree\n"); goto err; } splaytree_onremove(pairs, (splaytree_onremove_t)tracepair_onremove); while(filec_open != 0) { for(i=0; i<filec; i++) { if(file[i] == NULL) continue; if(scamper_file_read(file[i], filter, &type, (void *)&trace) != 0) { fprintf(stderr, "could not read from %s\n", files[i]); goto err; } if(trace == NULL) { filec_open--; scamper_file_close(file[i]); continue; } assert(type == SCAMPER_FILE_OBJ_TRACE); fm.tracec = 1; fm.traces[0] = trace; if((pair = splaytree_find(pairs, &fm)) == NULL) { if((pair = malloc_zero(sizeof(tracepair_t))) == NULL) goto err; pair->traces[i] = trace; pair->tracec = 1; if((pair->node = splaytree_insert(pairs, pair)) == NULL) goto err; } else { if(pair->traces[i] != NULL) { fprintf(stderr, "repeated trace for %s\n", scamper_addr_tostr(trace->dst, buf, sizeof(buf))); goto err; } pair->traces[i] = trace; pair->tracec++; } if(pair->tracec != filec) continue; splaytree_remove_node(pairs, pair->node); tracepair_process(pair); tracepair_free(pair); } } return 0; err: return -1; }
static void tracepair_dump(const tracepair_t *pair) { scamper_trace_t *trace; struct tm *tm; time_t tt; uint8_t min_ttl; uint8_t max_ttl; int i, k; size_t w, ws[2]; char fs[32], a[256], b[256]; /* there needs to be two traces for a pairwise comparison */ if(pair->tracec != 2) return; /* print the header of the traceroute */ trace = pair->traces[0]; for(i=1; i<pair->tracec; i++) if(scamper_addr_cmp(trace->dst, pair->traces[i]->dst) != 0) break; w = 0; string_concat(a, sizeof(a), &w, "traceroute "); if(i == pair->tracec) string_concat(a, sizeof(a), &w, "from %s ", scamper_addr_tostr(trace->src, b, sizeof(b))); string_concat(a, sizeof(a), &w, "to %s", scamper_addr_tostr(trace->dst, b, sizeof(b))); if(options & OPT_NAMES && addr_toname(trace->dst, b, sizeof(b)) != NULL) string_concat(a, sizeof(a), &w, " (%s)", b); printf("%s\n", a); max_ttl = 0; min_ttl = 0; for(k=0; k<pair->tracec; k++) { trace = pair->traces[k]; if(max_ttl < trace->hop_count) max_ttl = trace->hop_count; if(min_ttl == 0 || min_ttl > trace->firsthop) min_ttl = trace->firsthop; } for(k=0; k<pair->tracec; k++) { ws[k] = 8; trace = pair->traces[0]; for(i=0; i<trace->hop_count; i++) { w = sizeof(a); hop_tostr(trace, i, a, &w); if(w > ws[k]) ws[k] = w; } } snprintf(fs, sizeof(fs), " %%-%ds %%-%ds\n", (int)ws[0], (int)ws[1]); tt = pair->traces[0]->start.tv_sec; tm = localtime(&tt); snprintf(a, sizeof(a), "%02d:%02d:%02d",tm->tm_hour,tm->tm_min,tm->tm_sec); tt = pair->traces[1]->start.tv_sec; tm = localtime(&tt); snprintf(b, sizeof(b), "%02d:%02d:%02d",tm->tm_hour,tm->tm_min,tm->tm_sec); printf(fs, a, b); snprintf(fs, sizeof(fs), "%%2d %%-%ds %%-%ds\n", (int)ws[0], (int)ws[1]); for(i=min_ttl-1; i<max_ttl; i++) { ws[0] = sizeof(a); ws[1] = sizeof(b); printf(fs, i+1, hop_tostr(pair->traces[0], i, a, &ws[0]), hop_tostr(pair->traces[1], i, b, &ws[1])); } return; }
static char *hop_tostr(const scamper_trace_t *trace, int i, char *buf, size_t *len_out) { scamper_trace_hop_t *hop; char addr[128]; size_t len = *len_out, off = 0; if(i<trace->firsthop-1 || trace->hop_count <= i) { string_concat(buf, len, &off, "-"); goto done; } else if((hop = trace->hops[i]) == NULL) { string_concat(buf, len, &off, "*"); goto done; } if((options & OPT_NAMES) == 0 || addr_toname(hop->hop_addr, addr, sizeof(addr)) == NULL) scamper_addr_tostr(hop->hop_addr, addr, sizeof(addr)); string_concat(buf, len, &off, "%s", addr); if(SCAMPER_TRACE_HOP_IS_ICMP_TTL_EXP(hop) || SCAMPER_TRACE_HOP_IS_ICMP_ECHO_REPLY(hop) || SCAMPER_TRACE_HOP_IS_TCP(hop)) { goto done; } if(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4) { if(hop->hop_icmp_type == ICMP_UNREACH) { if(hop->hop_icmp_code == ICMP_UNREACH_FILTER_PROHIB) string_concat(buf, len, &off, " !X"); else if(hop->hop_icmp_code == ICMP_UNREACH_HOST) string_concat(buf, len, &off, " !H"); else if(hop->hop_icmp_code == ICMP_UNREACH_NEEDFRAG) string_concat(buf, len, &off, " !F"); else if(hop->hop_icmp_code == ICMP_UNREACH_SRCFAIL) string_concat(buf, len, &off, " !S"); else if(hop->hop_icmp_code == ICMP_UNREACH_PROTOCOL) string_concat(buf, len, &off, " !P"); else if(hop->hop_icmp_code == ICMP_UNREACH_NET) string_concat(buf, len, &off, " !N"); else if(hop->hop_icmp_code != ICMP_UNREACH_PORT) string_concat(buf, len, &off, " !<%d>", hop->hop_icmp_code); } else { string_concat(buf, len, &off, " !<%d,%d>", hop->hop_icmp_type, hop->hop_icmp_code); } } else if(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6) { if(hop->hop_icmp_type == ICMP6_DST_UNREACH) { if(hop->hop_icmp_code == ICMP6_DST_UNREACH_ADDR) string_concat(buf, len, &off, " !A"); else if(hop->hop_icmp_code == ICMP6_DST_UNREACH_BEYONDSCOPE) string_concat(buf, len, &off, " !S"); else if(hop->hop_icmp_code == ICMP6_DST_UNREACH_ADMIN) string_concat(buf, len, &off, " !P"); else if(hop->hop_icmp_code == ICMP6_DST_UNREACH_NOROUTE) string_concat(buf, len, &off, " !N"); else if(hop->hop_icmp_code != ICMP6_DST_UNREACH_NOPORT) string_concat(buf, len, &off, " !<%d>", hop->hop_icmp_code); } else if(hop->hop_icmp_type == ICMP6_PACKET_TOO_BIG) { string_concat(buf, len, &off, " !F"); } else { string_concat(buf, len, &off, " !<%d,%d>", hop->hop_icmp_type, hop->hop_icmp_code); } } done: *len_out = off; return buf; }
static char *ping_reply(const scamper_ping_t *ping, const scamper_ping_reply_t *reply) { scamper_ping_reply_v4rr_t *v4rr; scamper_ping_reply_v4ts_t *v4ts; char buf[256], a[64], rtt[32], *tcp, flags[16], tso[16], tsr[16], tst[16]; uint8_t i; size_t off = 0; scamper_addr_tostr(reply->addr, a, sizeof(a)); timeval_tostr(&reply->rtt, rtt, sizeof(rtt)); if(SCAMPER_PING_REPLY_IS_ICMP(reply)) { string_concat(buf, sizeof(buf), &off, "%d bytes from %s, seq=%d ttl=%d time=%s ms", reply->reply_size, a, reply->probe_id, reply->reply_ttl, rtt); if(reply->tsreply != NULL) string_concat(buf, sizeof(buf), &off, " tso=%s tsr=%s tst=%s", tsreply_tostr(tso,sizeof(tso),reply->tsreply->tso), tsreply_tostr(tsr,sizeof(tsr),reply->tsreply->tsr), tsreply_tostr(tst,sizeof(tst),reply->tsreply->tst)); string_concat(buf, sizeof(buf), &off, "\n"); } else if(SCAMPER_PING_REPLY_IS_TCP(reply)) { if((reply->tcp_flags & TH_RST) != 0) { tcp = "closed"; } else if((reply->tcp_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) { if((reply->tcp_flags & TH_ECE) != 0) tcp = "open,ecn"; else tcp = "open"; } else { snprintf(flags, sizeof(flags), "%0x02x", reply->tcp_flags); tcp = flags; } string_concat(buf, sizeof(buf), &off, "%d bytes from %s, seq=%d tcp=%s ttl=%d time=%s ms\n", reply->reply_size, a, reply->probe_id, tcp, reply->reply_ttl, rtt); } else { return NULL; } if((v4rr = reply->v4rr) != NULL) { string_concat(buf, sizeof(buf), &off, " RR: %s\n", scamper_addr_tostr(v4rr->rr[0], a, sizeof(a))); for(i=1; i<v4rr->rrc; i++) string_concat(buf, sizeof(buf), &off, " %s\n", scamper_addr_tostr(v4rr->rr[i], a, sizeof(a))); } if((v4ts = reply->v4ts) != NULL && v4ts->tsc > 0) { string_concat(buf, sizeof(buf), &off, " TS: "); if(v4ts->ips != NULL) string_concat(buf, sizeof(buf), &off, "%-15s ", scamper_addr_tostr(v4ts->ips[0], a, sizeof(a))); string_concat(buf, sizeof(buf), &off, "%d\n", v4ts->tss[0]); for(i=1; i<v4ts->tsc; i++) { string_concat(buf, sizeof(buf), &off, " "); if(v4ts->ips != NULL) string_concat(buf, sizeof(buf), &off, "%-15s ", scamper_addr_tostr(v4ts->ips[i], a, sizeof(a))); string_concat(buf, sizeof(buf), &off, "%d\n", v4ts->tss[i]); } } return strdup(buf); }
static char *hop_tostr(const scamper_trace_t *trace, scamper_trace_hop_t *hop) { char buf[512], tmp[128]; size_t off = 0; string_concat(buf, sizeof(buf), &off, "SCAMPER.%s", SCAMPER_VERSION); /* by DEFAULT 0; but can be changed using -U, perhaps a SK unit id */ string_concat(buf, sizeof(buf), &off, ";%u", trace->userid); string_concat(buf, sizeof(buf), &off, ";%u", trace->start.tv_sec); /*strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&tt));*/ /*string_concat(buf, sizeof(buf), &off,*/ /*", \"start\":{\"sec\":%u, \"usec\":%u, \"ftime\":\"%s\"}",*/ /*trace->start.tv_sec, trace->start.tv_usec, tmp);*/ string_concat(buf, sizeof(buf), &off, ";%s", scamper_addr_tostr(trace->src, tmp, sizeof(tmp))); string_concat(buf, sizeof(buf), &off, ";%s", scamper_addr_tostr(trace->dst, tmp, sizeof(tmp))); const char *ptr; if((ptr = scamper_trace_type_tostr(trace)) != NULL) string_concat(buf, sizeof(buf), &off, ";%s", ptr); else string_concat(buf, sizeof(buf), &off, ";%u", trace->type); /*if(SCAMPER_TRACE_TYPE_IS_UDP(trace) || SCAMPER_TRACE_TYPE_IS_TCP(trace))*/ /*string_concat(buf, sizeof(buf), &off, ";%u;%u", trace->sport,*/ /*trace->dport);*/ /*else if(trace->flags & SCAMPER_TRACE_FLAG_ICMPCSUMDP)*/ /*string_concat(buf, sizeof(buf), &off, ";%u", trace->dport);*/ string_concat(buf, sizeof(buf), &off, ";%s", stop_reason_tostr(trace->stop_reason, tmp, sizeof(tmp))); /*string_concat(buf, sizeof(buf), &off, "%u", trace->stop_data);*/ string_concat(buf, sizeof(buf), &off, ";%u", hop->hop_probe_ttl); string_concat(buf, sizeof(buf), &off, ";%s", scamper_addr_tostr(hop->hop_addr, tmp, sizeof(tmp))); /*string_concat(buf, sizeof(buf), &off, ";%u;%u", hop->hop_probe_id,*/ /*hop->hop_probe_size);*/ string_concat(buf, sizeof(buf), &off, ";%s", timeval_tostr(&hop->hop_rtt, tmp, sizeof(tmp))); /*string_concat(buf, sizeof(buf), &off, ";%u;%u;%u", hop->hop_reply_ttl,*/ /*hop->hop_reply_tos, hop->hop_reply_size);*/ /*string_concat(buf, sizeof(buf), &off, ";%u", hop->hop_reply_ipid);*/ if(SCAMPER_TRACE_HOP_IS_ICMP(hop)) { /*string_concat(buf, sizeof(buf), &off, ";%u;%u", hop->hop_icmp_type,*/ /*hop->hop_icmp_code);*/ if(SCAMPER_TRACE_HOP_IS_ICMP_Q(hop)) { /*string_concat(buf, sizeof(buf), &off, ";%u;%u", hop->hop_icmp_q_ttl,*/ /*hop->hop_icmp_q_ipl);*/ /*if(SCAMPER_ADDR_TYPE_IS_IPV4(hop->hop_addr))*/ /*string_concat(buf, sizeof(buf), &off, ";%u", hop->hop_icmp_q_tos);*/ } /*if(SCAMPER_TRACE_HOP_IS_ICMP_PTB(hop))*/ /*string_concat(buf, sizeof(buf), &off, "%u", hop->hop_icmp_nhmtu);*/ } else { /*string_concat(buf, sizeof(buf), &off, ";%u", hop->hop_tcp_flags); */ } /*string_concat(buf, sizeof(buf), &off,*/ /*", \"hop_count\":%u, \"attempts\":%u, \"hoplimit\":%u",*/ /*trace->hop_count, trace->attempts, trace->hoplimit);*/ /*string_concat(buf, sizeof(buf), &off,*/ /*", \"firsthop\":%u, \"wait\":%u, \"wait_probe\":%u",*/ /*trace->firsthop, trace->wait, trace->wait_probe);*/ /*string_concat(buf, sizeof(buf), &off, ", \"tos\":%u, \"probe_size\":%u",*/ /*trace->tos, trace->probe_size);*/ string_concat(buf, sizeof(buf), &off, "\n", NULL); return strdup(buf); }
static void probe_print(scamper_probe_t *probe) { size_t iphl; char tcp[16]; char pos[32]; char addr[128]; char icmp[16]; char tos[8]; assert(probe->pr_ip_dst != NULL); scamper_addr_tostr(probe->pr_ip_dst, addr, sizeof(addr)); tos[0] = '\0'; icmp[0] = '\0'; if(probe->pr_ip_proto == IPPROTO_TCP) { if((probe->pr_ip_tos & IPTOS_ECN_CE) == IPTOS_ECN_CE) snprintf(tos, sizeof(tos), ", ce"); else if(probe->pr_ip_tos & IPTOS_ECN_ECT1) snprintf(tos, sizeof(tos), ", ect1"); else if(probe->pr_ip_tos & IPTOS_ECN_ECT0) snprintf(tos, sizeof(tos), ", ect0"); } if(probe->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4) { if(scamper_ip4_hlen(probe, &iphl) != 0) return; if((probe->pr_ip_off & IP_OFFMASK) != 0) { scamper_debug("tx", "frag %s %04x:%d ttl %d, len %d", addr, probe->pr_ip_id, probe->pr_ip_off << 3, probe->pr_ip_ttl, iphl + probe->pr_len); return; } switch(probe->pr_ip_proto) { case IPPROTO_UDP: scamper_debug("tx", "udp %s, ttl %d, %d:%d, len %d", addr, probe->pr_ip_ttl, probe->pr_udp_sport, probe->pr_udp_dport, iphl + 8 + probe->pr_len); break; case IPPROTO_TCP: scamper_debug("tx", "tcp %s%s, ttl %d, %d:%d%s, ipid %04x, %s, len %d", addr, tos, probe->pr_ip_ttl, probe->pr_tcp_sport, probe->pr_tcp_dport, tcp_flags(tcp, sizeof(tcp), probe), probe->pr_ip_id, tcp_pos(pos, sizeof(pos), probe), iphl + scamper_tcp4_hlen(probe) + probe->pr_len); break; case IPPROTO_ICMP: if(probe->pr_icmp_type == ICMP_ECHO) { if(probe->pr_icmp_sum != 0) { snprintf(icmp, sizeof(icmp), ", sum %04x", ntohs(probe->pr_icmp_sum)); } scamper_debug("tx", "icmp %s echo, ttl %d%s, seq %d, len %d", addr, probe->pr_ip_ttl, icmp, probe->pr_icmp_seq, iphl + 8 + probe->pr_len); } else if(probe->pr_icmp_type == ICMP_UNREACH) { if(probe->pr_icmp_code == ICMP_UNREACH_NEEDFRAG) snprintf(icmp,sizeof(icmp),"ptb %d", probe->pr_icmp_mtu); else snprintf(icmp,sizeof(icmp),"unreach %d", probe->pr_icmp_code); scamper_debug("tx", "icmp %s %s, len %d", addr, icmp, iphl + 8 + probe->pr_len); } else { scamper_debug("tx", "icmp %s type %d, code %d, len %d", addr, probe->pr_icmp_type, probe->pr_icmp_code, iphl + 8 + probe->pr_len); } break; } } else if(probe->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV6) { if(scamper_ip6_hlen(probe, &iphl) != 0) return; if(probe->pr_ip_off != 0) { scamper_debug("tx", "frag %s off %04x, ttl %d, len %d", addr, probe->pr_ip_off, probe->pr_ip_ttl, iphl + probe->pr_len); return; } switch(probe->pr_ip_proto) { case IPPROTO_UDP: scamper_debug("tx", "udp %s, ttl %d, %d:%d, len %d", addr, probe->pr_ip_ttl, probe->pr_udp_sport, probe->pr_udp_dport, iphl + 8 + probe->pr_len); break; case IPPROTO_TCP: scamper_debug("tx", "tcp %s%s, ttl %d, %d:%d%s, %s, len %d", addr, tos, probe->pr_ip_ttl, probe->pr_tcp_sport, probe->pr_tcp_dport, tcp_flags(tcp, sizeof(tcp), probe), tcp_pos(pos, sizeof(pos), probe), iphl + scamper_tcp6_hlen(probe) + probe->pr_len); break; case IPPROTO_ICMPV6: if(probe->pr_icmp_type == ICMP6_ECHO_REQUEST) { if(probe->pr_icmp_sum != 0) { snprintf(icmp, sizeof(icmp), ", sum %04x", ntohs(probe->pr_icmp_sum)); } scamper_debug("tx", "icmp %s echo, ttl %d%s, seq %d, len %d", addr, probe->pr_ip_ttl, icmp, probe->pr_icmp_seq, iphl + 8 + probe->pr_len); } else if(probe->pr_icmp_type == ICMP6_PACKET_TOO_BIG) { scamper_debug("tx", "icmp %s ptb %d, len %d", addr, probe->pr_icmp_mtu, iphl + 8 + probe->pr_len); } else if(probe->pr_icmp_type == ICMP6_DST_UNREACH) { scamper_debug("tx", "icmp %s unreach %d, len %d", addr, probe->pr_icmp_code, iphl + 8 + probe->pr_len); } else { scamper_debug("tx", "icmp %s type %d, code %d, len %d", addr, probe->pr_icmp_type, probe->pr_icmp_code, iphl + 8 + probe->pr_len); } break; } } return; }
int scamper_file_text_tbit_write(const scamper_file_t *sf, const scamper_tbit_t *tbit) { scamper_tbit_pkt_t *pkt; scamper_tbit_app_http_t *http; char buf[131072]; char src[64], dst[64], tmp[256], ipid[12], fstr[32], tfstr[32], sack[128]; struct timeval diff; uint32_t i; uint32_t seq, ack, server_isn, client_isn, off, id, u32; uint16_t len, u16, datalen; uint8_t proto, flags, iphlen, tcphlen, mf, ecn, u8, *ptr; size_t soff = 0, toff; int frag; int fd = scamper_file_getfd(sf); ipid[0] = '\0'; string_concat(buf, sizeof(buf), &soff, "tbit from %s to %s\n server-mss %d, result: %s\n", scamper_addr_tostr(tbit->src, src, sizeof(src)), scamper_addr_tostr(tbit->dst, dst, sizeof(dst)), tbit->server_mss, scamper_tbit_res2str(tbit, tmp, sizeof(tmp))); if(tbit->app_proto == SCAMPER_TBIT_APP_HTTP && tbit->app_data != NULL) { http = tbit->app_data; string_concat(buf, sizeof(buf), &soff, " app: http"); if(http->host != NULL && http->file != NULL) string_concat(buf, sizeof(buf), &soff, ", url: http://%s%s", http->host, http->file); else if(http->host != NULL) string_concat(buf, sizeof(buf), &soff, ", url: http://%s", http->host); else string_concat(buf, sizeof(buf), &soff, ", file: %s", http->file); string_concat(buf, sizeof(buf), &soff, "\n"); } client_isn = 0; server_isn = 0; for(i=0; i<tbit->pktc; i++) { pkt = tbit->pkts[i]; frag = 0; mf = 0; id = 0; off = 0; if((pkt->data[0] >> 4) == 4) { iphlen = (pkt->data[0] & 0xf) * 4; len = bytes_ntohs(pkt->data+2); proto = pkt->data[9]; ecn = pkt->data[1] & 0x3; if(pkt->data[6] & 0x20) mf = 1; id = bytes_ntohs(pkt->data+4); off = (bytes_ntohs(pkt->data+6) & 0x1fff) * 8; if(mf != 0 || off != 0) frag = 1; snprintf(ipid, sizeof(ipid), " %04x", bytes_ntohs(pkt->data+4)); } else if((pkt->data[0] >> 4) == 6) { iphlen = 40; len = bytes_ntohs(pkt->data+4) + iphlen; proto = pkt->data[6]; ecn = (pkt->data[1] & 0x30) >> 4; for(;;) { switch(proto) { case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: proto = pkt->data[iphlen+0]; iphlen += (pkt->data[iphlen+1] * 8) + 8; continue; case IPPROTO_FRAGMENT: if(pkt->data[iphlen+3] & 0x1) mf = 1; off = (bytes_ntohs(pkt->data+iphlen+2) & 0xfff8); id = bytes_ntohl(pkt->data+iphlen+4); proto = pkt->data[iphlen+0]; iphlen += 8; frag = 1; continue; } break; } } else { continue;