1 /*
2 * sc_wartsdump
3 *
4 * $Id: sc_wartsdump.c,v 1.233 2021/10/23 04:46:52 mjl Exp $
5 *
6 * Matthew Luckie
7 * mjl@luckie.org.nz
8 *
9 * Copyright (C) 2004-2006 Matthew Luckie
10 * Copyright (C) 2006-2011 The University of Waikato
11 * Copyright (C) 2012-2015 The Regents of the University of California
12 * Copyright (C) 2019-2021 Matthew Luckie
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, version 2.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include "internal.h"
33
34 #include "scamper_addr.h"
35 #include "scamper_list.h"
36 #include "scamper_icmpext.h"
37 #include "trace/scamper_trace.h"
38 #include "ping/scamper_ping.h"
39 #include "tracelb/scamper_tracelb.h"
40 #include "dealias/scamper_dealias.h"
41 #include "neighbourdisc/scamper_neighbourdisc.h"
42 #include "tbit/scamper_tbit.h"
43 #include "sting/scamper_sting.h"
44 #include "sniff/scamper_sniff.h"
45 #include "host/scamper_host.h"
46 #include "scamper_file.h"
47 #include "utils.h"
48
usage()49 static void usage()
50 {
51 fprintf(stderr, "usage: sc_wartsdump <file>\n");
52 return;
53 }
54
icmp_unreach_tostr(char * buf,size_t len,int at,uint8_t co)55 static char *icmp_unreach_tostr(char *buf, size_t len, int at, uint8_t co)
56 {
57 char *p = NULL;
58
59 if(at == SCAMPER_ADDR_TYPE_IPV4)
60 {
61 switch(co)
62 {
63 case ICMP_UNREACH_NET: p = "net"; break;
64 case ICMP_UNREACH_HOST: p = "host"; break;
65 case ICMP_UNREACH_PROTOCOL: p = "protocol"; break;
66 case ICMP_UNREACH_PORT: p = "port"; break;
67 case ICMP_UNREACH_SRCFAIL: p = "src-rt failed"; break;
68 case ICMP_UNREACH_NET_UNKNOWN: p = "net unknown"; break;
69 case ICMP_UNREACH_HOST_UNKNOWN: p = "host unknown"; break;
70 case ICMP_UNREACH_ISOLATED: p = "isolated"; break;
71 case ICMP_UNREACH_NET_PROHIB: p = "net prohib"; break;
72 case ICMP_UNREACH_HOST_PROHIB: p = "host prohib"; break;
73 case ICMP_UNREACH_TOSNET: p = "tos net"; break;
74 case ICMP_UNREACH_TOSHOST: p = "tos host"; break;
75 case ICMP_UNREACH_FILTER_PROHIB: p = "admin prohib"; break;
76 case ICMP_UNREACH_NEEDFRAG: p = "need frag"; break;
77 }
78 }
79 else
80 {
81 switch(co)
82 {
83 case ICMP6_DST_UNREACH_NOROUTE: p = "no route"; break;
84 case ICMP6_DST_UNREACH_ADMIN: p = "admin prohib"; break;
85 case ICMP6_DST_UNREACH_BEYONDSCOPE: p = "beyond scope"; break;
86 case ICMP6_DST_UNREACH_ADDR: p = "addr"; break;
87 case ICMP6_DST_UNREACH_NOPORT: p = "port"; break;
88 }
89 }
90
91 if(p != NULL)
92 snprintf(buf, len, "%s", p);
93 else
94 snprintf(buf, len, "%d", co);
95
96 return buf;
97 }
98
dump_list_summary(scamper_list_t * list)99 static void dump_list_summary(scamper_list_t *list)
100 {
101 if(list != NULL)
102 {
103 printf(" list id: %d", list->id);
104 if(list->name != NULL)
105 printf(", name: %s", list->name);
106 if(list->monitor != NULL)
107 printf(", monitor: %s", list->monitor);
108 printf("\n");
109 }
110 return;
111 }
112
dump_cycle_summary(scamper_cycle_t * cycle)113 static void dump_cycle_summary(scamper_cycle_t *cycle)
114 {
115 if(cycle != NULL)
116 printf(" cycle id: %d\n", cycle->id);
117 return;
118 }
119
dump_tcp_flags(uint8_t flags)120 static void dump_tcp_flags(uint8_t flags)
121 {
122 if(flags != 0)
123 {
124 printf(" (%s%s%s%s%s%s%s%s )",
125 (flags & 0x01) ? " fin" : "",
126 (flags & 0x02) ? " syn" : "",
127 (flags & 0x04) ? " rst" : "",
128 (flags & 0x08) ? " psh" : "",
129 (flags & 0x10) ? " ack" : "",
130 (flags & 0x20) ? " urg" : "",
131 (flags & 0x40) ? " ece" : "",
132 (flags & 0x80) ? " cwr" : "");
133 }
134 return;
135 }
136
dump_timeval(const char * label,struct timeval * start)137 static void dump_timeval(const char *label, struct timeval *start)
138 {
139 time_t tt = start->tv_sec;
140 char buf[32];
141 memcpy(buf, ctime(&tt), 24); buf[24] = '\0';
142 printf(" %s: %s %06d\n", label, buf, (int)start->tv_usec);
143 return;
144 }
145
dump_trace_hop(const scamper_trace_t * trace,scamper_trace_hop_t * hop)146 static void dump_trace_hop(const scamper_trace_t *trace,
147 scamper_trace_hop_t *hop)
148 {
149 struct timeval tv;
150 scamper_icmpext_t *ie;
151 uint32_t u32;
152 char addr[256];
153 int i;
154 char *comma = "";
155
156 printf("hop %2d %s",
157 hop->hop_probe_ttl,
158 scamper_addr_tostr(hop->hop_addr, addr, sizeof(addr)));
159 if(hop->hop_name != NULL)
160 printf(" name %s", hop->hop_name);
161 printf("\n");
162
163 printf(" attempt: %d", hop->hop_probe_id);
164 if(hop->hop_tx.tv_sec != 0)
165 {
166 timeval_diff_tv(&tv, &trace->start, &hop->hop_tx);
167 printf(", tx: %d.%06ds", (int)tv.tv_sec, (int)tv.tv_usec);
168 }
169 printf(", rtt: %d.%06ds, probe-size: %d\n",
170 (int)hop->hop_rtt.tv_sec, (int)hop->hop_rtt.tv_usec,
171 hop->hop_probe_size);
172
173 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_REPLY_TTL)
174 {
175 printf("%s reply-ttl: %d", comma, hop->hop_reply_ttl);
176 comma = ",";
177 }
178
179 if((trace->flags & SCAMPER_TRACE_FLAG_RXERR) == 0)
180 {
181 printf("%s reply-size: %d", comma, hop->hop_reply_size);
182 comma = ",";
183 if(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4)
184 printf("%s reply-ipid: 0x%04x", comma, hop->hop_reply_ipid);
185 }
186
187 if(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4)
188 printf("%s reply-tos 0x%02x", comma, hop->hop_reply_tos);
189
190 if(comma[0] != '\0')
191 printf("\n");
192
193 if(SCAMPER_TRACE_HOP_IS_ICMP(hop))
194 {
195 printf(" icmp-type: %d, icmp-code: %d",
196 hop->hop_icmp_type, hop->hop_icmp_code);
197 if(SCAMPER_TRACE_HOP_IS_ICMP_Q(hop))
198 {
199 printf(", q-ttl: %d, q-len: %d",
200 hop->hop_icmp_q_ttl, hop->hop_icmp_q_ipl);
201 if(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4)
202 printf(", q-tos %d", hop->hop_icmp_q_tos);
203 }
204 if(SCAMPER_TRACE_HOP_IS_ICMP_PTB(hop))
205 printf(", nhmtu: %d", hop->hop_icmp_nhmtu);
206 printf("\n");
207 }
208 else if(SCAMPER_TRACE_HOP_IS_TCP(hop))
209 {
210 printf(" tcp-flags: 0x%02x", hop->hop_tcp_flags);
211 dump_tcp_flags(hop->hop_tcp_flags);
212 printf("\n");
213 }
214
215 printf(" flags: 0x%02x", hop->hop_flags);
216 if(hop->hop_flags != 0)
217 {
218 printf(" (");
219 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_SOCK_RX)
220 printf(" sockrxts");
221 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_TX)
222 printf(" dltxts");
223 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_RX)
224 printf(" dlrxts");
225 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_TSC)
226 printf(" tscrtt");
227 if(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_REPLY_TTL)
228 printf(" replyttl");
229 printf(" )");
230 }
231 printf("\n");
232
233 for(ie = hop->hop_icmpext; ie != NULL; ie = ie->ie_next)
234 {
235 if(SCAMPER_ICMPEXT_IS_MPLS(ie))
236 {
237 for(i=0; i<SCAMPER_ICMPEXT_MPLS_COUNT(ie); i++)
238 {
239 u32 = SCAMPER_ICMPEXT_MPLS_LABEL(ie, i);
240 printf("%9s ttl: %d, s: %d, exp: %d, label: %d\n",
241 (i == 0) ? "mpls ext" : "",
242 SCAMPER_ICMPEXT_MPLS_TTL(ie, i),
243 SCAMPER_ICMPEXT_MPLS_S(ie, i),
244 SCAMPER_ICMPEXT_MPLS_EXP(ie, i), u32);
245 }
246 }
247 }
248
249 return;
250 }
251
dump_trace(scamper_trace_t * trace)252 static void dump_trace(scamper_trace_t *trace)
253 {
254 scamper_trace_hop_t *hop;
255 scamper_trace_pmtud_t *pmtud;
256 scamper_trace_pmtud_n_t *n;
257 uint16_t u16;
258 uint8_t u8;
259 char buf[256];
260 int i;
261
262 if(trace->src != NULL)
263 {
264 scamper_addr_tostr(trace->src, buf, sizeof(buf));
265 printf("traceroute from %s to ", buf);
266 scamper_addr_tostr(trace->dst, buf, sizeof(buf));
267 printf("%s\n", buf);
268 }
269 else
270 {
271 printf("traceroute to %s\n",
272 scamper_addr_tostr(trace->dst, buf, sizeof(buf)));
273 }
274
275 dump_list_summary(trace->list);
276 dump_cycle_summary(trace->cycle);
277 printf(" user-id: %d\n", trace->userid);
278 if(trace->rtr != NULL)
279 printf(" rtr: %s\n", scamper_addr_tostr(trace->rtr, buf, sizeof(buf)));
280 dump_timeval("start", &trace->start);
281
282 printf(" type: ");
283 switch(trace->type)
284 {
285 case SCAMPER_TRACE_TYPE_ICMP_ECHO:
286 printf("icmp, echo id: %d", trace->sport);
287 break;
288
289 case SCAMPER_TRACE_TYPE_ICMP_ECHO_PARIS:
290 /*
291 * if the byte ordering of the trace->sport used in the icmp csum
292 * is unknown -- that is, not known to be correct, print that detail
293 */
294 printf("icmp paris, echo id: %d", trace->sport);
295 if(SCAMPER_TRACE_IS_ICMPCSUMDP(trace))
296 printf(", csum: 0x%04x", trace->dport);
297 break;
298
299 case SCAMPER_TRACE_TYPE_UDP:
300 printf("udp, sport: %d, base dport: %d",
301 trace->sport, trace->dport);
302 break;
303
304 case SCAMPER_TRACE_TYPE_UDP_PARIS:
305 printf("udp paris, sport: %d, dport: %d",
306 trace->sport, trace->dport);
307 break;
308
309 case SCAMPER_TRACE_TYPE_TCP:
310 printf("tcp, sport: %d, dport: %d", trace->sport, trace->dport);
311 break;
312
313 case SCAMPER_TRACE_TYPE_TCP_ACK:
314 printf("tcp-ack, sport: %d, dport: %d",
315 trace->sport, trace->dport);
316 break;
317
318 default:
319 printf("%d", trace->type);
320 break;
321 }
322 if(trace->offset != 0)
323 printf(", offset %d", trace->offset);
324 printf("\n");
325
326 if(trace->dtree != NULL)
327 {
328 printf(" doubletree firsthop: %d", trace->dtree->firsthop);
329 if(trace->dtree->lss != NULL)
330 printf(", lss-name: %s", trace->dtree->lss);
331 if(trace->dtree->lss_stop != NULL)
332 printf(", lss-stop: %s",
333 scamper_addr_tostr(trace->dtree->lss_stop, buf, sizeof(buf)));
334 if(trace->dtree->gss_stop != NULL)
335 printf(", gss-stop: %s",
336 scamper_addr_tostr(trace->dtree->gss_stop, buf, sizeof(buf)));
337 printf("\n");
338 }
339
340 printf(" attempts: %d, hoplimit: %d, loops: %d, probec: %d\n",
341 trace->attempts, trace->hoplimit, trace->loops, trace->probec);
342 printf(" squeries: %d, gaplimit: %d, gapaction: ",
343 trace->squeries, trace->gaplimit);
344 if(trace->gapaction == SCAMPER_TRACE_GAPACTION_STOP)
345 printf("stop");
346 else if(trace->gapaction == SCAMPER_TRACE_GAPACTION_LASTDITCH)
347 printf("lastditch");
348 else
349 printf("0x%02x", trace->gapaction);
350 printf("\n");
351
352 printf(" wait-timeout: %ds", trace->wait);
353 if(trace->wait_probe != 0)
354 printf(", wait-probe: %dms", trace->wait_probe * 10);
355 if(trace->confidence != 0)
356 printf(", confidence: %d%%", trace->confidence);
357 printf("\n");
358
359 printf(" flags: 0x%02x", trace->flags);
360 if(trace->flags != 0)
361 {
362 printf(" (");
363 if(trace->flags & SCAMPER_TRACE_FLAG_ALLATTEMPTS)
364 printf(" all-attempts");
365 if(trace->flags & SCAMPER_TRACE_FLAG_PMTUD)
366 printf(" pmtud");
367 if(trace->flags & SCAMPER_TRACE_FLAG_DL)
368 printf(" dl");
369 if(trace->flags & SCAMPER_TRACE_FLAG_IGNORETTLDST)
370 printf(" ignorettldst");
371 if(trace->flags & SCAMPER_TRACE_FLAG_DOUBLETREE)
372 printf(" doubletree");
373 if(trace->flags & SCAMPER_TRACE_FLAG_ICMPCSUMDP)
374 printf(" icmp-csum-dport");
375 if(trace->flags & SCAMPER_TRACE_FLAG_CONSTPAYLOAD)
376 printf(" const-payload");
377 if(trace->flags & SCAMPER_TRACE_FLAG_RXERR)
378 printf(" rxerr");
379 if(trace->flags & SCAMPER_TRACE_FLAG_PTR)
380 printf(" ptr");
381 printf(" )");
382 }
383 printf("\n");
384
385 printf(" stop reason: ");
386 switch(trace->stop_reason)
387 {
388 case SCAMPER_TRACE_STOP_NONE:
389 printf("none");
390 break;
391
392 case SCAMPER_TRACE_STOP_COMPLETED:
393 printf("done");
394 break;
395
396 case SCAMPER_TRACE_STOP_UNREACH:
397 i = trace->dst->type;
398 printf("icmp unreach %s",
399 icmp_unreach_tostr(buf, sizeof(buf), i, trace->stop_data));
400 break;
401
402 case SCAMPER_TRACE_STOP_ICMP:
403 printf("icmp type %d", trace->stop_data);
404 break;
405
406 case SCAMPER_TRACE_STOP_LOOP:
407 printf("loop");
408 break;
409
410 case SCAMPER_TRACE_STOP_GAPLIMIT:
411 printf("gaplimit");
412 break;
413
414 case SCAMPER_TRACE_STOP_ERROR:
415 printf("errno %d", trace->stop_data);
416 break;
417
418 case SCAMPER_TRACE_STOP_HOPLIMIT:
419 printf("hoplimit");
420 break;
421
422 case SCAMPER_TRACE_STOP_GSS:
423 printf("dtree-gss");
424 break;
425
426 case SCAMPER_TRACE_STOP_HALTED:
427 printf("halted");
428 break;
429
430 default:
431 printf("reason 0x%02x data 0x%02x",trace->stop_reason,trace->stop_data);
432 break;
433 }
434 printf("\n");
435
436 for(u16=0; u16<trace->hop_count; u16++)
437 for(hop = trace->hops[u16]; hop != NULL; hop = hop->hop_next)
438 dump_trace_hop(trace, hop);
439
440 /* dump any last-ditch probing hops */
441 for(hop = trace->lastditch; hop != NULL; hop = hop->hop_next)
442 dump_trace_hop(trace, hop);
443
444 if((pmtud = trace->pmtud) != NULL)
445 {
446 printf("pmtud: ver %d ifmtu %d, pmtu %d", pmtud->ver, pmtud->ifmtu,
447 pmtud->pmtu);
448 if(pmtud->outmtu != 0)
449 printf(", outmtu %d", pmtud->outmtu);
450 if(pmtud->notec != 0)
451 printf(", notec %d", pmtud->notec);
452 printf("\n");
453 for(u8=0; u8<pmtud->notec; u8++)
454 {
455 n = pmtud->notes[u8];
456 hop = n->hop;
457 printf(" note %d: nhmtu %d, ", u8, n->nhmtu);
458
459 if(hop != NULL)
460 scamper_addr_tostr(hop->hop_addr, buf, sizeof(buf));
461 else
462 buf[0] = '\0';
463
464 if(n->type == SCAMPER_TRACE_PMTUD_N_TYPE_PTB)
465 printf("ptb %s", buf);
466 else if(n->type == SCAMPER_TRACE_PMTUD_N_TYPE_PTB_BAD && hop != NULL)
467 printf("ptb-bad %s mtu %d", buf, hop->hop_icmp_nhmtu);
468 else if(n->type == SCAMPER_TRACE_PMTUD_N_TYPE_SILENCE)
469 printf("silence > ttl %d", hop != NULL ? hop->hop_probe_ttl : 0);
470 else
471 printf("type-%d", n->type);
472 printf("\n");
473 }
474 for(hop = trace->pmtud->hops; hop != NULL; hop = hop->hop_next)
475 dump_trace_hop(trace, hop);
476 }
477
478 printf("\n");
479
480 scamper_trace_free(trace);
481
482 return;
483 }
484
dump_tracelb_reply(scamper_tracelb_probe_t * probe,scamper_tracelb_reply_t * reply)485 static void dump_tracelb_reply(scamper_tracelb_probe_t *probe,
486 scamper_tracelb_reply_t *reply)
487 {
488 scamper_icmpext_t *ie;
489 struct timeval rtt;
490 char from[32];
491 uint32_t u32;
492 uint16_t m;
493
494 timeval_diff_tv(&rtt, &probe->tx, &reply->reply_rx);
495
496 if(reply->reply_from != NULL)
497 scamper_addr_tostr(reply->reply_from, from, sizeof(from));
498 else
499 snprintf(from, sizeof(from), "<null>");
500
501 printf(" reply from: %s, rtt: %d.%06d, ttl: %d",
502 from, (int)rtt.tv_sec, (int)rtt.tv_usec, reply->reply_ttl);
503
504 if(reply->reply_from != NULL && SCAMPER_ADDR_TYPE_IS_IPV4(reply->reply_from))
505 printf(", ipid: 0x%04x", reply->reply_ipid);
506 printf("\n");
507
508 if(reply->reply_flags & SCAMPER_TRACELB_REPLY_FLAG_TCP)
509 {
510 printf(" tcp flags 0x%02x", reply->reply_tcp_flags);
511 dump_tcp_flags(reply->reply_tcp_flags);
512 printf("\n");
513 }
514 else
515 {
516 printf(" icmp: %d/%d, q-tos: 0x%02x",
517 reply->reply_icmp_type, reply->reply_icmp_code,
518 reply->reply_icmp_q_tos);
519 if(SCAMPER_TRACELB_REPLY_IS_ICMP_UNREACH(reply) ||
520 SCAMPER_TRACELB_REPLY_IS_ICMP_TTL_EXP(reply))
521 {
522 printf(", q-ttl: %d", reply->reply_icmp_q_ttl);
523 }
524 printf("\n");
525
526 for(ie = reply->reply_icmp_ext; ie != NULL; ie = ie->ie_next)
527 {
528 if(SCAMPER_ICMPEXT_IS_MPLS(ie))
529 {
530 for(m=0; m<SCAMPER_ICMPEXT_MPLS_COUNT(ie); m++)
531 {
532 u32 = SCAMPER_ICMPEXT_MPLS_LABEL(ie, m);
533 printf(" %9s: label %d exp %d s %d ttl %d\n",
534 (m == 0) ? " icmp-ext mpls" : "", u32,
535 SCAMPER_ICMPEXT_MPLS_EXP(ie, m),
536 SCAMPER_ICMPEXT_MPLS_S(ie, m),
537 SCAMPER_ICMPEXT_MPLS_TTL(ie, m));
538 }
539 }
540 }
541 }
542
543 return;
544 }
545
dump_tracelb_probe(scamper_tracelb_t * trace,scamper_tracelb_probe_t * probe)546 static void dump_tracelb_probe(scamper_tracelb_t *trace,
547 scamper_tracelb_probe_t *probe)
548 {
549 uint32_t i;
550
551 printf(" probe flowid: %d, ttl: %d, attempt: %d, tx: %d.%06d\n",
552 probe->flowid, probe->ttl, probe->attempt,
553 (int)probe->tx.tv_sec, (int)probe->tx.tv_usec);
554
555 for(i=0; i<probe->rxc; i++)
556 {
557 dump_tracelb_reply(probe, probe->rxs[i]);
558 }
559
560 return;
561 }
562
dump_tracelb(scamper_tracelb_t * trace)563 static void dump_tracelb(scamper_tracelb_t *trace)
564 {
565 static const char *flags[] = {
566 "ptr"
567 };
568 scamper_tracelb_link_t *link;
569 scamper_tracelb_node_t *node;
570 scamper_tracelb_probeset_t *set;
571 char src[256], dst[256];
572 uint16_t i, j, k, l;
573
574 if(trace->src != NULL)
575 {
576 printf("tracelb from %s to %s\n",
577 scamper_addr_tostr(trace->src, src, sizeof(src)),
578 scamper_addr_tostr(trace->dst, dst, sizeof(dst)));
579 }
580 else
581 {
582 printf("tracelb to %s\n",
583 scamper_addr_tostr(trace->dst, dst, sizeof(dst)));
584 }
585
586 dump_list_summary(trace->list);
587 dump_cycle_summary(trace->cycle);
588 printf(" user-id: %d\n", trace->userid);
589 if(trace->rtr != NULL)
590 printf(" rtr: %s\n", scamper_addr_tostr(trace->rtr, src, sizeof(src)));
591 dump_timeval("start", &trace->start);
592
593 printf(" type: ");
594 switch(trace->type)
595 {
596 case SCAMPER_TRACELB_TYPE_ICMP_ECHO:
597 printf("icmp-echo id: %d", trace->sport);
598 break;
599
600 case SCAMPER_TRACELB_TYPE_UDP_DPORT:
601 printf("udp-dport %d:%d", trace->sport, trace->dport);
602 break;
603
604 case SCAMPER_TRACELB_TYPE_UDP_SPORT:
605 printf("udp-sport %d:%d", trace->sport, trace->dport);
606 break;
607
608 case SCAMPER_TRACELB_TYPE_TCP_SPORT:
609 printf("tcp-sport %d:%d", trace->sport, trace->dport);
610 break;
611
612 case SCAMPER_TRACELB_TYPE_TCP_ACK_SPORT:
613 printf("tcp-ack-sport %d:%d", trace->sport, trace->dport);
614 break;
615
616 default:
617 printf("%d", trace->type);
618 break;
619 }
620 printf(", tos: 0x%02x\n", trace->tos);
621
622 printf(" firsthop: %d, attempts: %d, confidence: %d\n",
623 trace->firsthop, trace->attempts, trace->confidence);
624 printf(" probe-size: %d, wait-probe: %dms, wait-timeout %ds\n",
625 trace->probe_size, trace->wait_probe * 10, trace->wait_timeout);
626 printf(" nodec: %d, linkc: %d, probec: %d, probec_max: %d\n",
627 trace->nodec, trace->linkc, trace->probec, trace->probec_max);
628 if(trace->flags != 0)
629 {
630 printf(" flags:");
631 l = 0;
632 for(i=0; i<1; i++)
633 {
634 if((trace->flags & (0x1 << i)) == 0)
635 continue;
636 if(l > 0)
637 printf(",");
638 printf(" %s", flags[i]);
639 l++;
640 }
641 printf("\n");
642 }
643
644 for(i=0; i<trace->nodec; i++)
645 {
646 node = trace->nodes[i];
647
648 if(node->addr != NULL)
649 scamper_addr_tostr(node->addr, src, sizeof(src));
650 else
651 snprintf(src, sizeof(src), "*");
652
653 printf("node %d %s", i, src);
654 if(SCAMPER_TRACELB_NODE_QTTL(node) != 0)
655 printf(", q-ttl %d", node->q_ttl);
656 if(node->name != NULL)
657 printf(", name %s", node->name);
658 printf("\n");
659
660 for(j=0; j<node->linkc; j++)
661 {
662 link = node->links[j];
663 if(link->from->addr != NULL)
664 scamper_addr_tostr(link->from->addr, src, sizeof(src));
665 else
666 snprintf(src, sizeof(src), "*");
667 if(link->to != NULL)
668 scamper_addr_tostr(link->to->addr, dst, sizeof(dst));
669 else
670 snprintf(dst, sizeof(dst), "*");
671 printf(" link %s -> %s hopc %d\n", src, dst, link->hopc);
672
673 for(k=0; k<link->hopc; k++)
674 {
675 set = link->sets[k];
676 for(l=0; l<set->probec; l++)
677 dump_tracelb_probe(trace, set->probes[l]);
678 }
679 }
680 }
681
682 printf("\n");
683
684 scamper_tracelb_free(trace);
685 return;
686 }
687
ping_tsreply_tostr(char * buf,size_t len,uint32_t val)688 static char *ping_tsreply_tostr(char *buf, size_t len, uint32_t val)
689 {
690 uint32_t hh, mm, ss, ms;
691 ms = val % 1000;
692 ss = val / 1000;
693 hh = ss / 3600; ss -= (hh * 3600);
694 mm = ss / 60; ss -= (mm * 60);
695 snprintf(buf, len, "%02d:%02d:%02d.%03d", hh, mm, ss, ms);
696 return buf;
697 }
698
dump_ping_reply(const scamper_ping_t * ping,const scamper_ping_reply_t * reply)699 static void dump_ping_reply(const scamper_ping_t *ping,
700 const scamper_ping_reply_t *reply)
701 {
702 scamper_ping_reply_v4rr_t *v4rr;
703 scamper_ping_reply_v4ts_t *v4ts;
704 scamper_ping_reply_tsreply_t *tsreply;
705 uint8_t i;
706 char buf[256];
707 struct timeval txoff;
708
709 printf("reply from %s, attempt: %d",
710 scamper_addr_tostr(reply->addr, buf, sizeof(buf)), reply->probe_id+1);
711 if(timeval_cmp(&reply->tx, &ping->start) >= 0)
712 {
713 timeval_diff_tv(&txoff, &ping->start, &reply->tx);
714 printf(", tx: %d.%06ds", (int)txoff.tv_sec, (int)txoff.tv_usec);
715 }
716 printf(", rtt: %d.%06ds\n", (int)reply->rtt.tv_sec, (int)reply->rtt.tv_usec);
717
718 printf(" size: %d", reply->reply_size);
719 if(reply->flags & SCAMPER_PING_REPLY_FLAG_REPLY_TTL)
720 printf(", ttl: %d", reply->reply_ttl);
721 if(reply->flags & SCAMPER_PING_REPLY_FLAG_PROBE_IPID)
722 printf(", probe-ipid: 0x%04x", reply->probe_ipid);
723 if(reply->flags & SCAMPER_PING_REPLY_FLAG_REPLY_IPID)
724 {
725 if(SCAMPER_ADDR_TYPE_IS_IPV4(reply->addr))
726 printf(", reply-ipid: 0x%04x", reply->reply_ipid);
727 else
728 printf(", reply-ipid32: 0x%08x", reply->reply_ipid32);
729 }
730 printf("\n");
731
732 if(SCAMPER_PING_REPLY_IS_ICMP(reply))
733 {
734 printf(" icmp type: %d, code: %d\n", reply->icmp_type, reply->icmp_code);
735 }
736 else if(SCAMPER_PING_REPLY_IS_TCP(reply))
737 {
738 printf(" tcp flags: %02x", reply->tcp_flags);
739 dump_tcp_flags(reply->tcp_flags);
740 printf("\n");
741 }
742
743 if((tsreply = reply->tsreply) != NULL)
744 {
745 printf(" icmp-tsreply:");
746 printf(" tso=%s", ping_tsreply_tostr(buf, sizeof(buf), tsreply->tso));
747 printf(" tsr=%s", ping_tsreply_tostr(buf, sizeof(buf), tsreply->tsr));
748 printf(" tst=%s\n", ping_tsreply_tostr(buf, sizeof(buf), tsreply->tst));
749 }
750
751 if((v4rr = reply->v4rr) != NULL)
752 {
753 printf(" record route:");
754 for(i=0; i<v4rr->rrc; i++)
755 {
756 if((i % 3) == 0 && i != 0)
757 printf("\n ");
758
759 printf(" %-15s",
760 scamper_addr_tostr(v4rr->rr[i],buf,sizeof(buf)));
761 }
762 printf("\n");
763 }
764
765 if((v4ts = reply->v4ts) != NULL)
766 {
767 printf(" IP timestamp option: tsc %d", v4ts->tsc);
768 if(v4ts->ips != NULL)
769 {
770 for(i=0; i<v4ts->tsc; i++)
771 {
772 if((i % 2) == 0)
773 printf("\n ");
774 else if(i != 0)
775 printf(" ");
776
777 printf("%-15s 0x%08x",
778 scamper_addr_tostr(v4ts->ips[i], buf, sizeof(buf)),
779 v4ts->tss[i]);
780 }
781 }
782 else
783 {
784 for(i=0; i<v4ts->tsc; i++)
785 {
786 if((i % 3) == 0)
787 printf("\n ");
788 printf(" 0x%08x", v4ts->tss[i]);
789 }
790 }
791 printf("\n");
792 }
793
794 return;
795 }
796
dump_ping(scamper_ping_t * ping)797 static void dump_ping(scamper_ping_t *ping)
798 {
799 static const char *flags[] = {
800 "v4rr", "spoof", "payload", "tsonly", "tsandaddr", "icmpsum", "dl", "tbt",
801 "nosrc",
802 };
803 scamper_ping_reply_t *reply;
804 char buf[256];
805 uint32_t u32;
806 int i;
807
808 scamper_addr_tostr(ping->src, buf, sizeof(buf));
809 printf("ping from %s", buf);
810 if(ping->flags & SCAMPER_PING_FLAG_SPOOF)
811 printf(" (spoofed)");
812 scamper_addr_tostr(ping->dst, buf, sizeof(buf));
813 printf(" to %s\n", buf);
814
815 dump_list_summary(ping->list);
816 dump_cycle_summary(ping->cycle);
817 printf(" user-id: %d\n", ping->userid);
818 if(ping->rtr != NULL)
819 printf(" rtr: %s\n", scamper_addr_tostr(ping->rtr, buf, sizeof(buf)));
820 dump_timeval("start", &ping->start);
821
822 printf(" probe-count: %d", ping->probe_count);
823 if(ping->reply_count > 0)
824 printf(", replies-req: %d", ping->reply_count);
825 printf(", size: %d", ping->probe_size);
826 if(ping->reply_pmtu > 0)
827 printf(", reply-pmtu: %d", ping->reply_pmtu);
828 printf(", wait: %u", ping->probe_wait);
829 if(ping->probe_wait_us > 0)
830 {
831 u32 = ping->probe_wait_us;
832 while((u32 % 10) == 0)
833 u32 /= 10;
834 printf(".%u", u32);
835 }
836 printf(", timeout: %u, ttl: %u", ping->probe_timeout, ping->probe_ttl);
837 printf("\n");
838
839 if(ping->flags != 0)
840 {
841 printf(" flags:");
842 u32 = 0;
843 for(i=0; i<9; i++)
844 {
845 if((ping->flags & (0x1 << i)) == 0)
846 continue;
847 if(u32 > 0)
848 printf(",");
849 printf(" %s", flags[i]);
850 u32++;
851 }
852 printf("\n");
853 }
854
855 printf(" method: %s", scamper_ping_method2str(ping, buf, sizeof(buf)));
856 switch(ping->probe_method)
857 {
858 case SCAMPER_PING_METHOD_ICMP_ECHO:
859 case SCAMPER_PING_METHOD_ICMP_TIME:
860 if((ping->flags & SCAMPER_PING_FLAG_ICMPSUM) != 0)
861 printf(", icmp-csum: %04x", ping->probe_icmpsum);
862 break;
863
864 case SCAMPER_PING_METHOD_UDP:
865 case SCAMPER_PING_METHOD_TCP_ACK:
866 case SCAMPER_PING_METHOD_TCP_SYN:
867 case SCAMPER_PING_METHOD_TCP_RST:
868 case SCAMPER_PING_METHOD_TCP_SYNACK:
869 printf(", sport: %d, dport: %d", ping->probe_sport, ping->probe_dport);
870 break;
871
872 case SCAMPER_PING_METHOD_TCP_ACK_SPORT:
873 printf(", base-sport: %d, dport: %d",
874 ping->probe_sport, ping->probe_dport);
875 break;
876
877 case SCAMPER_PING_METHOD_UDP_DPORT:
878 printf(", sport: %d, base-dport %d",
879 ping->probe_sport, ping->probe_dport);
880 break;
881 }
882
883 if(SCAMPER_PING_METHOD_IS_TCP(ping))
884 printf(", seq: %u, ack: %u", ping->probe_tcpseq, ping->probe_tcpack);
885
886 printf("\n");
887
888 if(ping->probe_tsps != NULL)
889 {
890 printf(" timestamp-prespec:");
891 for(i=0; i<ping->probe_tsps->ipc; i++)
892 printf(" %s",
893 scamper_addr_tostr(ping->probe_tsps->ips[i],buf,sizeof(buf)));
894 printf("\n");
895 }
896
897 /* dump pad bytes, if used */
898 if(ping->probe_datalen > 0 && ping->probe_data != NULL)
899 {
900 if((ping->flags & SCAMPER_PING_FLAG_PAYLOAD) != 0)
901 printf(" payload");
902 else
903 printf(" pattern");
904 printf(" bytes (%d): ", ping->probe_datalen);
905 for(i=0; i<ping->probe_datalen; i++)
906 printf("%02x", ping->probe_data[i]);
907 printf("\n");
908 }
909
910 printf(" probes-sent: %d, stop-reason: ", ping->ping_sent);
911 switch(ping->stop_reason)
912 {
913 case SCAMPER_PING_STOP_NONE:
914 printf("none"); break;
915
916 case SCAMPER_PING_STOP_COMPLETED:
917 printf("done"); break;
918
919 case SCAMPER_PING_STOP_ERROR:
920 printf("sendto errno %d", ping->stop_data); break;
921
922 case SCAMPER_PING_STOP_HALTED:
923 printf("halted"); break;
924
925 default:
926 printf("reason 0x%02x data 0x%02x",
927 ping->stop_reason, ping->stop_data);
928 break;
929 }
930 printf("\n");
931
932 for(i=0; i<ping->ping_sent; i++)
933 {
934 for(reply = ping->ping_replies[i]; reply != NULL; reply = reply->next)
935 {
936 dump_ping_reply(ping, reply);
937 }
938 }
939
940 printf("\n");
941
942 scamper_ping_free(ping);
943
944 return;
945 }
946
dump_dealias_probedef(scamper_dealias_probedef_t * def)947 static void dump_dealias_probedef(scamper_dealias_probedef_t *def)
948 {
949 scamper_dealias_probedef_icmp_t *icmp;
950 char dst[128], src[128];
951
952 printf(" probedef %d: dst: %s, ttl: %d, tos: 0x%02x\n src: %s",
953 def->id,
954 scamper_addr_tostr(def->dst, dst, sizeof(dst)),
955 def->ttl, def->tos,
956 scamper_addr_tostr(def->src, src, sizeof(src)));
957 if(def->size > 0)
958 printf(", size: %d", def->size);
959 if(def->mtu > 0)
960 printf(", mtu: %d", def->mtu);
961 printf("\n");
962
963 if(SCAMPER_DEALIAS_PROBEDEF_PROTO_IS_ICMP(def))
964 {
965 icmp = &def->un.icmp;
966 printf(" icmp-echo csum: %04x, id: %04x\n", icmp->csum, icmp->id);
967 }
968 else if(SCAMPER_DEALIAS_PROBEDEF_PROTO_IS_UDP(def))
969 {
970 if(def->method == SCAMPER_DEALIAS_PROBEDEF_METHOD_UDP)
971 printf(" udp");
972 else if(def->method == SCAMPER_DEALIAS_PROBEDEF_METHOD_UDP_DPORT)
973 printf(" udp-dport");
974 else
975 printf(" udp-%d", def->method);
976 printf(" %d:%d\n", def->un.udp.sport, def->un.udp.dport);
977 }
978 else if(SCAMPER_DEALIAS_PROBEDEF_PROTO_IS_TCP(def))
979 {
980 if(def->method == SCAMPER_DEALIAS_PROBEDEF_METHOD_TCP_ACK)
981 printf(" tcp-ack");
982 else if(def->method == SCAMPER_DEALIAS_PROBEDEF_METHOD_TCP_ACK_SPORT)
983 printf(" tcp-ack-sport");
984 else if(def->method == SCAMPER_DEALIAS_PROBEDEF_METHOD_TCP_SYN_SPORT)
985 printf(" tcp-syn-sport");
986 else
987 printf(" tcp-%d", def->method);
988 printf(" %d:%d ", def->un.tcp.sport, def->un.tcp.dport);
989 dump_tcp_flags(def->un.tcp.flags);
990 printf("\n");
991 }
992 else
993 {
994 printf("%d\n", def->method);
995 }
996 return;
997 }
998
dump_dealias(scamper_dealias_t * dealias)999 static void dump_dealias(scamper_dealias_t *dealias)
1000 {
1001 scamper_dealias_prefixscan_t *ps = dealias->data;
1002 scamper_dealias_mercator_t *mercator = dealias->data;
1003 scamper_dealias_radargun_t *radargun = dealias->data;
1004 scamper_dealias_ally_t *ally = dealias->data;
1005 scamper_dealias_bump_t *bump = dealias->data;
1006 scamper_dealias_probe_t *probe;
1007 scamper_dealias_reply_t *reply;
1008 struct timeval rtt;
1009 uint32_t i;
1010 uint16_t u16;
1011 uint8_t u8;
1012 char buf[256];
1013 int j;
1014
1015 /* first line: dealias */
1016 printf("dealias");
1017 if(dealias->method == SCAMPER_DEALIAS_METHOD_MERCATOR)
1018 {
1019 scamper_addr_tostr(mercator->probedef.src, buf, sizeof(buf));
1020 printf(" from %s", buf);
1021 scamper_addr_tostr(mercator->probedef.dst, buf, sizeof(buf));
1022 printf(" to %s", buf);
1023 }
1024 printf("\n");
1025
1026 /* dump list, cycle, start time */
1027 dump_list_summary(dealias->list);
1028 dump_cycle_summary(dealias->cycle);
1029 printf(" user-id: %d\n", dealias->userid);
1030 dump_timeval("start", &dealias->start);
1031
1032 /* method headers */
1033 printf(" method: ");
1034 if(dealias->method == SCAMPER_DEALIAS_METHOD_MERCATOR)
1035 {
1036 printf("mercator, attempts: %d, timeout: %ds\n",
1037 mercator->attempts, mercator->wait_timeout);
1038 dump_dealias_probedef(&mercator->probedef);
1039 }
1040 else if(dealias->method == SCAMPER_DEALIAS_METHOD_ALLY)
1041 {
1042 printf("ally, attempts: %d, fudge: %d, "
1043 "wait-probe: %dms, wait-timeout: %ds",
1044 ally->attempts,ally->fudge,ally->wait_probe,ally->wait_timeout);
1045 if(SCAMPER_DEALIAS_ALLY_IS_NOBS(dealias))
1046 printf(", nobs");
1047 printf("\n");
1048
1049 dump_dealias_probedef(&ally->probedefs[0]);
1050 dump_dealias_probedef(&ally->probedefs[1]);
1051 }
1052 else if(dealias->method == SCAMPER_DEALIAS_METHOD_BUMP)
1053 {
1054 printf("bump, attempts: %d, wait-probe: %dms, bump-limit: %d\n",
1055 bump->attempts, bump->wait_probe, bump->bump_limit);
1056 dump_dealias_probedef(&bump->probedefs[0]);
1057 dump_dealias_probedef(&bump->probedefs[1]);
1058 }
1059 else if(dealias->method == SCAMPER_DEALIAS_METHOD_RADARGUN)
1060 {
1061 printf("radargun, wait-probe: %dms, wait-round: %dms\n"
1062 " wait-timeout: %ds, attempts: %d, probedefc: %d\n",
1063 radargun->wait_probe, radargun->wait_round,
1064 radargun->wait_timeout, radargun->attempts, radargun->probedefc);
1065 if((u8 = radargun->flags) != 0)
1066 {
1067 printf(" flags: ");
1068 for(i=0; i<8; i++)
1069 {
1070 if((u8 & (1 << i)) == 0)
1071 continue;
1072 switch(1 << i)
1073 {
1074 case SCAMPER_DEALIAS_RADARGUN_FLAG_SHUFFLE:
1075 printf("shuffle");
1076 break;
1077
1078 default:
1079 printf("0x%02x", 1<<i);
1080 break;
1081 }
1082
1083 u8 &= ~(1 << i);
1084 if(u8 != 0)
1085 printf(", ");
1086 else
1087 break;
1088 }
1089 printf("\n");
1090 }
1091 for(i=0; i<radargun->probedefc; i++)
1092 dump_dealias_probedef(&radargun->probedefs[i]);
1093 }
1094 else if(dealias->method == SCAMPER_DEALIAS_METHOD_PREFIXSCAN)
1095 {
1096 printf("prefixscan, %s:",
1097 scamper_addr_tostr(ps->a, buf, sizeof(buf)));
1098 printf("%s/%d",
1099 scamper_addr_tostr(ps->b, buf, sizeof(buf)), ps->prefix);
1100 if(ps->ab != NULL)
1101 printf(", alias: %s/%d",
1102 scamper_addr_tostr(ps->ab, buf, sizeof(buf)),
1103 scamper_addr_prefixhosts(ps->b, ps->ab));
1104 printf("\n");
1105
1106 printf(" attempts: %d, replyc: %d, fudge: %d, wait-probe: %dms, "
1107 "wait-timeout: %ds", ps->attempts, ps->replyc, ps->fudge,
1108 ps->wait_probe, ps->wait_timeout);
1109 if(SCAMPER_DEALIAS_PREFIXSCAN_IS_NOBS(dealias))
1110 printf(", nobs");
1111 printf("\n");
1112 if(ps->xc > 0)
1113 {
1114 printf(" exclude:");
1115 for(u16=0; u16<ps->xc; u16++)
1116 printf(" %s", scamper_addr_tostr(ps->xs[u16], buf, sizeof(buf)));
1117 printf("\n");
1118 }
1119 for(i=0; i<ps->probedefc; i++)
1120 dump_dealias_probedef(&ps->probedefs[i]);
1121 }
1122 else
1123 {
1124 printf("%d\n", dealias->method);
1125 }
1126
1127 printf(" probes: %d, result: %s", dealias->probec,
1128 scamper_dealias_result_tostr(dealias, buf, sizeof(buf)));
1129
1130 if(dealias->method == SCAMPER_DEALIAS_METHOD_PREFIXSCAN &&
1131 ps->flags & SCAMPER_DEALIAS_PREFIXSCAN_FLAG_CSA)
1132 printf(", csa");
1133 printf("\n");
1134
1135 for(i=0; i<dealias->probec; i++)
1136 {
1137 probe = dealias->probes[i];
1138 printf(" probe: %d, def: %d, seq: %d, tx: %d.%06d",
1139 i, probe->def->id, probe->seq,
1140 (int)probe->tx.tv_sec, (int)probe->tx.tv_usec);
1141 if(SCAMPER_ADDR_TYPE_IS_IPV4(probe->def->dst))
1142 printf(", ipid: %04x", probe->ipid);
1143 printf("\n");
1144
1145 for(j=0; j<probe->replyc; j++)
1146 {
1147 reply = probe->replies[j];
1148 timeval_diff_tv(&rtt, &probe->tx, &reply->rx);
1149 printf(" reply: %d, src: %s, ttl: %d, rtt: %d.%06d",
1150 j, scamper_addr_tostr(reply->src, buf, sizeof(buf)),
1151 reply->ttl, (int)rtt.tv_sec, (int)rtt.tv_usec);
1152 if(SCAMPER_ADDR_TYPE_IS_IPV4(reply->src))
1153 printf(", ipid: %04x", reply->ipid);
1154 else if(reply->flags & SCAMPER_DEALIAS_REPLY_FLAG_IPID32)
1155 printf(", ipid32: %08x", reply->ipid32);
1156 printf("\n");
1157
1158 if(SCAMPER_DEALIAS_REPLY_IS_ICMP(reply))
1159 {
1160 printf(" icmp-type: %d, icmp-code: %d",
1161 reply->icmp_type, reply->icmp_code);
1162
1163 if(SCAMPER_DEALIAS_REPLY_IS_ICMP_UNREACH(reply) ||
1164 SCAMPER_DEALIAS_REPLY_IS_ICMP_TTL_EXP(reply))
1165 {
1166 printf(", icmp-q-ttl: %d", reply->icmp_q_ip_ttl);
1167 }
1168 printf("\n");
1169 }
1170 else if(SCAMPER_DEALIAS_REPLY_IS_TCP(reply))
1171 {
1172 printf(" tcp flags:");
1173 dump_tcp_flags(reply->tcp_flags);
1174 printf("\n");
1175 }
1176 else
1177 {
1178 printf(" reply proto %d\n", reply->proto);
1179 }
1180 }
1181 }
1182
1183 printf("\n");
1184
1185 scamper_dealias_free(dealias);
1186 return;
1187 }
1188
dump_neighbourdisc(scamper_neighbourdisc_t * nd)1189 static void dump_neighbourdisc(scamper_neighbourdisc_t *nd)
1190 {
1191 scamper_neighbourdisc_probe_t *probe;
1192 scamper_neighbourdisc_reply_t *reply;
1193 struct timeval rtt;
1194 uint16_t i, j;
1195 char buf[128];
1196
1197 printf("neighbourdisc\n");
1198 dump_list_summary(nd->list);
1199 dump_cycle_summary(nd->cycle);
1200 printf(" user-id: %d\n", nd->userid);
1201 dump_timeval("start", &nd->start);
1202
1203 if(nd->method == SCAMPER_NEIGHBOURDISC_METHOD_ARP ||
1204 nd->method == SCAMPER_NEIGHBOURDISC_METHOD_ND_NSOL)
1205 {
1206 if(nd->method == SCAMPER_NEIGHBOURDISC_METHOD_ARP)
1207 printf(" method: arp");
1208 else
1209 printf(" method: ipv6 nsol");
1210
1211 printf(", attempts: %d, wait: %ds, replyc: %d, iface: %s\n",
1212 nd->attempts, nd->wait, nd->replyc, nd->ifname);
1213 printf(" our-mac: %s\n",
1214 scamper_addr_tostr(nd->src_mac, buf, sizeof(buf)));
1215 printf(" flags: 0x%02x", nd->flags);
1216 if(nd->flags != 0)
1217 {
1218 printf(" (");
1219 if(nd->flags & SCAMPER_NEIGHBOURDISC_FLAG_ALLATTEMPTS)
1220 printf(" all-attempts");
1221 if(nd->flags & SCAMPER_NEIGHBOURDISC_FLAG_FIRSTRESPONSE)
1222 printf(" first-response");
1223 printf(" )");
1224 }
1225 printf("\n");
1226 printf(" query: who-has %s",
1227 scamper_addr_tostr(nd->dst_ip, buf, sizeof(buf)));
1228 if(nd->src_ip != NULL)
1229 printf(" tell %s", scamper_addr_tostr(nd->src_ip, buf, sizeof(buf)));
1230 if(nd->dst_mac != NULL)
1231 printf(" result: %s is-at %s\n", buf,
1232 scamper_addr_tostr(nd->dst_mac, buf, sizeof(buf)));
1233 }
1234
1235 for(i=0; i<nd->probec; i++)
1236 {
1237 probe = nd->probes[i];
1238 printf(" probe: %d, tx: %d.%06d\n",
1239 i, (int)probe->tx.tv_sec, (int)probe->tx.tv_usec);
1240
1241 for(j=0; j<probe->rxc; j++)
1242 {
1243 reply = probe->rxs[j];
1244 timeval_diff_tv(&rtt, &probe->tx, &reply->rx);
1245 printf(" reply: %d, rtt: %d.%06d, mac: %s\n",
1246 i, (int)rtt.tv_sec, (int)rtt.tv_usec,
1247 scamper_addr_tostr(reply->mac, buf, sizeof(buf)));
1248 }
1249 }
1250
1251 printf("\n");
1252
1253 scamper_neighbourdisc_free(nd);
1254 return;
1255 }
1256
tbit_bits_print(uint32_t flags,int bits,const char ** f2s,int f2sc)1257 static void tbit_bits_print(uint32_t flags,int bits, const char **f2s,int f2sc)
1258 {
1259 int i, f = 0;
1260 uint32_t u32;
1261
1262 if(flags == 0)
1263 return;
1264 for(i=0; i<bits; i++)
1265 {
1266 if((u32 = flags & (0x1 << i)) == 0) continue;
1267 if(f > 0) printf(",");
1268 if(i < f2sc)
1269 printf(" %s", f2s[i]);
1270 else
1271 printf(" 0x%x", u32);
1272 f++;
1273 }
1274 return;
1275 }
1276
tbit_isnoff(uint32_t isn,uint32_t seq)1277 static uint32_t tbit_isnoff(uint32_t isn, uint32_t seq)
1278 {
1279 if(seq >= isn)
1280 return seq - isn;
1281 return TCP_MAX_SEQNUM - isn + seq + 1;
1282 }
1283
dump_tbit(scamper_tbit_t * tbit)1284 static void dump_tbit(scamper_tbit_t *tbit)
1285 {
1286 static const char *tbit_options[] = {"tcpts", "sack"};
1287 static const char *null_options[] = {"tcpts", "ipts-syn", "iprr-syn",
1288 "ipqs-syn", "sack", "fo", "fo-exp"};
1289 static const char *null_results[] = {"tcpts-ok", "sack-ok", "fo-ok"};
1290 scamper_tbit_pmtud_t *pmtud;
1291 scamper_tbit_null_t *null;
1292 scamper_tbit_icw_t *icw;
1293 scamper_tbit_blind_t *blind;
1294 scamper_tbit_app_http_t *http;
1295 scamper_tbit_app_bgp_t *bgp;
1296 scamper_tbit_pkt_t *pkt;
1297 struct timeval diff;
1298 uint32_t i;
1299 uint16_t len, u16, datalen;
1300 uint8_t proto, flags, iphlen, tcphlen, mf, ecn, u8, *tmp, txsyn, rxsyn;
1301 uint32_t seq, ack, server_isn, client_isn, off, u32;
1302 char src[64], dst[64], buf[128], ipid[12], fstr[32], tfstr[32], sack[64];
1303 uint8_t cookie[16];
1304 char *str;
1305 size_t soff;
1306 int frag;
1307
1308 /* Start dumping the tbit test information */
1309 printf("tbit from %s to %s\n",
1310 scamper_addr_tostr(tbit->src, src, sizeof(src)),
1311 scamper_addr_tostr(tbit->dst, dst, sizeof(dst)));
1312
1313 dump_list_summary(tbit->list);
1314 dump_cycle_summary(tbit->cycle);
1315 printf(" user-id: %d\n", tbit->userid);
1316 dump_timeval("start", &tbit->start);
1317
1318 printf(" sport: %d, dport: %d\n", tbit->sport, tbit->dport);
1319 printf(" client-mss: %d, server-mss: %d, ttl: %u",
1320 tbit->client_mss, tbit->server_mss, tbit->ttl);
1321 if(tbit->wscale > 0)
1322 printf(", wscale: %u", tbit->wscale);
1323 printf("\n");
1324 printf(" type: %s,", scamper_tbit_type2str(tbit, buf, sizeof(buf)));
1325 printf(" result: %s\n", scamper_tbit_res2str(tbit, buf, sizeof(buf)));
1326 if(tbit->options != 0)
1327 {
1328 printf(" options:");
1329 tbit_bits_print(tbit->options, 32, tbit_options,
1330 sizeof(tbit_options) / sizeof(char *));
1331 printf("\n");
1332 }
1333
1334 if(tbit->fo_cookielen > 0)
1335 {
1336 printf(" fo-cookie: ");
1337 for(u8=0; u8<tbit->fo_cookielen; u8++)
1338 printf("%02x", tbit->fo_cookie[u8]);
1339 printf("\n");
1340 }
1341
1342 if(tbit->type == SCAMPER_TBIT_TYPE_PMTUD && tbit->data != NULL)
1343 {
1344 pmtud = tbit->data;
1345 printf(" mtu: %d, ptb-retx: %d", pmtud->mtu, pmtud->ptb_retx);
1346 if(pmtud->ptbsrc != NULL)
1347 printf(", ptb-src: %s",
1348 scamper_addr_tostr(pmtud->ptbsrc, src, sizeof(src)));
1349 if(pmtud->options & SCAMPER_TBIT_PMTUD_OPTION_BLACKHOLE)
1350 printf(", blackhole");
1351 printf("\n");
1352 }
1353 else if(tbit->type == SCAMPER_TBIT_TYPE_NULL && tbit->data != NULL)
1354 {
1355 null = tbit->data;
1356 if(null->options != 0)
1357 {
1358 printf(" null-options:");
1359 tbit_bits_print(null->options, 16, null_options,
1360 sizeof(null_options) / sizeof(char *));
1361 printf("\n");
1362 }
1363 if(null->results != 0)
1364 {
1365 printf(" results:");
1366 tbit_bits_print(null->results, 16, null_results,
1367 sizeof(null_results) / sizeof(char *));
1368 printf("\n");
1369
1370 if((null->results & SCAMPER_TBIT_NULL_RESULT_FO) &&
1371 scamper_tbit_fo_getcookie(tbit, cookie, &u8) != 0)
1372 {
1373 printf(" fo-cookie: ");
1374 for(i=0; i<u8; i++)
1375 printf("%02x", cookie[i]);
1376 printf("\n");
1377 }
1378 }
1379 }
1380 else if(tbit->type == SCAMPER_TBIT_TYPE_ICW &&
1381 tbit->result == SCAMPER_TBIT_RESULT_ICW_SUCCESS)
1382 {
1383 icw = tbit->data;
1384 printf(" icw-start-seq: %u", icw->start_seq);
1385 if(scamper_tbit_icw_size(tbit, &u32) == 0)
1386 printf(", icw-size: %u bytes", u32);
1387 printf("\n");
1388 }
1389 else if(tbit->type == SCAMPER_TBIT_TYPE_BLIND_RST ||
1390 tbit->type == SCAMPER_TBIT_TYPE_BLIND_SYN ||
1391 tbit->type == SCAMPER_TBIT_TYPE_BLIND_DATA)
1392 {
1393 blind = tbit->data;
1394 printf(" blind: offset %d, retx %u\n", blind->off, blind->retx);
1395 }
1396
1397 if(tbit->app_proto == SCAMPER_TBIT_APP_HTTP && tbit->app_data != NULL)
1398 {
1399 http = tbit->app_data;
1400 printf(" app: http");
1401 if(http->type == SCAMPER_TBIT_APP_HTTP_TYPE_HTTPS)
1402 str = "https";
1403 else
1404 str = "http";
1405
1406 if(http->host != NULL && http->file != NULL)
1407 printf(", url: %s://%s%s", str, http->host, http->file);
1408 else if(http->host != NULL)
1409 printf(", url: %s://%s", str, http->host);
1410 else
1411 printf(", file: %s", http->file);
1412 printf("\n");
1413 }
1414 else if(tbit->app_proto == SCAMPER_TBIT_APP_BGP && tbit->app_data != NULL)
1415 {
1416 bgp = tbit->app_data;
1417 printf(" app: bgp, asn: %u\n", bgp->asn);
1418 }
1419
1420 client_isn = 0;
1421 server_isn = 0;
1422 txsyn = 0;
1423 rxsyn = 0;
1424
1425 for(i=0; i<tbit->pktc; i++)
1426 {
1427 pkt = tbit->pkts[i];
1428 frag = 0; mf = 0; off = 0;
1429 ipid[0] = '\0';
1430
1431 if((pkt->data[0] >> 4) == 4)
1432 {
1433 iphlen = (pkt->data[0] & 0xf) * 4;
1434 len = bytes_ntohs(pkt->data+2);
1435 proto = pkt->data[9];
1436 ecn = pkt->data[1] & 0x3;
1437 if(pkt->data[6] & 0x20)
1438 mf = 1;
1439 off = (bytes_ntohs(pkt->data+6) & 0x1fff) * 8;
1440 if(mf != 0 || off != 0)
1441 frag = 1;
1442 snprintf(ipid, sizeof(ipid), "%04x", bytes_ntohs(pkt->data+4));
1443 }
1444 else if((pkt->data[0] >> 4) == 6)
1445 {
1446 iphlen = 40;
1447 len = bytes_ntohs(pkt->data+4) + iphlen;
1448 proto = pkt->data[6];
1449 ecn = (pkt->data[1] & 0x30) >> 4;
1450
1451 for(;;)
1452 {
1453 switch(proto)
1454 {
1455 case IPPROTO_HOPOPTS:
1456 case IPPROTO_DSTOPTS:
1457 case IPPROTO_ROUTING:
1458 if(pkt->data[iphlen+1] == 0 ||
1459 255 - iphlen <= (pkt->data[iphlen+1] * 8) + 8)
1460 break;
1461 proto = pkt->data[iphlen+0];
1462 iphlen += (pkt->data[iphlen+1] * 8) + 8;
1463 continue;
1464
1465 case IPPROTO_FRAGMENT:
1466 if(255 - iphlen <= 8)
1467 break;
1468 if(pkt->data[iphlen+3] & 0x1)
1469 mf = 1;
1470 off = (bytes_ntohs(pkt->data+iphlen+2) & 0xfff8);
1471 snprintf(ipid, sizeof(ipid), "%x",
1472 bytes_ntohl(pkt->data+iphlen+4));
1473 proto = pkt->data[iphlen+0];
1474 iphlen += 8;
1475 frag = 1;
1476 continue;
1477 }
1478 break;
1479 }
1480 }
1481 else
1482 {
1483 continue;
1484 }
1485
1486 timeval_diff_tv(&diff, &tbit->start, &pkt->tv);
1487 printf(" [%3d.%03d] %s ", (int)diff.tv_sec, (int)(diff.tv_usec / 1000),
1488 pkt->dir == SCAMPER_TBIT_PKT_DIR_TX ? "TX" : "RX");
1489
1490 if(frag != 0)
1491 snprintf(fstr,sizeof(fstr),":%u%s", off, mf != 0 ? " MF" : "");
1492 else
1493 fstr[0] = '\0';
1494
1495 if(off != 0)
1496 {
1497 printf("%13s %4dF%17s%s%s", "", len, "", ipid, fstr);
1498 }
1499 else if(proto == IPPROTO_TCP)
1500 {
1501 seq = bytes_ntohl(pkt->data+iphlen+4);
1502 ack = bytes_ntohl(pkt->data+iphlen+8);
1503 flags = pkt->data[iphlen+13];
1504 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
1505
1506 soff = 0; tfstr[0] = '\0';
1507 if(flags & 0x2)
1508 {
1509 if(flags & 0x10)
1510 {
1511 if(rxsyn == 0)
1512 {
1513 server_isn = seq;
1514 rxsyn = 1;
1515 }
1516 string_concat(tfstr, sizeof(tfstr), &soff, "SYN/ACK");
1517 }
1518 else
1519 {
1520 if(txsyn == 0)
1521 {
1522 client_isn = seq;
1523 txsyn = 1;
1524 }
1525 string_concat(tfstr, sizeof(tfstr), &soff, "SYN");
1526 }
1527 }
1528 else if(flags & 0x1)
1529 string_concat(tfstr, sizeof(tfstr), &soff, "FIN");
1530 else if(flags & 0x4)
1531 string_concat(tfstr, sizeof(tfstr), &soff, "RST");
1532
1533 if(flags & 0x40)
1534 string_concat(tfstr, sizeof(tfstr), &soff, "%sECE",
1535 soff != 0 ? "/" : "");
1536 if(flags & 0x80)
1537 string_concat(tfstr, sizeof(tfstr), &soff, "%sCWR",
1538 soff != 0 ? "/" : "");
1539
1540 /* parse TCP options for sack blocks */
1541 u8 = 20; soff = 0; sack[0] = '\0';
1542 while(u8 < tcphlen)
1543 {
1544 tmp = pkt->data + iphlen + u8;
1545
1546 if(tmp[0] == 0) /* end of option list */
1547 break;
1548
1549 if(tmp[0] == 1) /* nop */
1550 {
1551 u8++;
1552 continue;
1553 }
1554
1555 if(tmp[1] == 0 || u8 + tmp[1] > tcphlen)
1556 break;
1557
1558 /* sack edges */
1559 if(tmp[0] == 5 &&
1560 (tmp[1]==10 || tmp[1]==18 || tmp[1]==26 || tmp[1]==34))
1561 {
1562 if(pkt->dir == SCAMPER_TBIT_PKT_DIR_TX)
1563 u32 = server_isn;
1564 else
1565 u32 = client_isn;
1566
1567 string_concat(sack, sizeof(sack), &soff, " {");
1568 for(u16=0; u16<(tmp[1]-2)/8; u16++)
1569 string_concat(sack, sizeof(sack), &soff, "%s%u:%u",
1570 u16 != 0 ? "," : "",
1571 bytes_ntohl(tmp+2+(u16*8)) - u32,
1572 bytes_ntohl(tmp+2+(u16*8)+4) - u32);
1573 string_concat(sack, sizeof(sack), &soff, "}");
1574 }
1575
1576 u8 += tmp[1];
1577 }
1578
1579 if(pkt->dir == SCAMPER_TBIT_PKT_DIR_TX)
1580 {
1581 seq = tbit_isnoff(client_isn, seq);
1582 ack = tbit_isnoff(server_isn, ack);
1583 }
1584 else
1585 {
1586 if(!(seq == 0 && (flags & TH_RST) != 0))
1587 seq = tbit_isnoff(server_isn, seq);
1588 ack = tbit_isnoff(client_isn, ack);
1589 }
1590
1591 datalen = len - iphlen - tcphlen;
1592
1593 printf("%-13s %4d%s", tfstr, len, frag != 0 ? "F" : " ");
1594 soff = 0;
1595 string_concat(buf, sizeof(buf), &soff, " %u", seq);
1596 if(flags & TH_ACK)
1597 string_concat(buf, sizeof(buf), &soff, ":%u", ack);
1598 if(datalen != 0)
1599 string_concat(buf, sizeof(buf), &soff, "(%d)", datalen);
1600 printf("%-17s%s", buf, ipid);
1601 if(frag != 0) printf("%s", fstr);
1602 if(datalen > 0 && (pkt->data[0] >> 4) == 4 && pkt->data[6] & 0x40)
1603 printf(" DF");
1604 if(ecn == 3) printf(" CE");
1605 else if(ecn != 0) printf(" ECT");
1606 printf("%s", sack);
1607 }
1608 else if(proto == IPPROTO_ICMP)
1609 {
1610 if(pkt->data[iphlen+0] == 3 && pkt->data[iphlen+1] == 4)
1611 {
1612 u16 = bytes_ntohs(pkt->data+iphlen+6);
1613 printf("%-13s %4d mtu = %d", "PTB", len, u16);
1614 }
1615 }
1616 else if(proto == IPPROTO_ICMPV6)
1617 {
1618 if(pkt->data[iphlen+0] == 2)
1619 {
1620 u32 = bytes_ntohl(pkt->data+iphlen+4);
1621 printf("%-13s %4d mtu = %d", "PTB", len, u32);
1622 }
1623 }
1624
1625 printf("\n");
1626 }
1627
1628 fprintf(stdout,"\n");
1629
1630 scamper_tbit_free(tbit);
1631 return;
1632 }
1633
dump_sting(scamper_sting_t * sting)1634 static void dump_sting(scamper_sting_t *sting)
1635 {
1636 scamper_sting_pkt_t *pkt;
1637 struct timeval diff;
1638 char src[64], dst[64], buf[32], ipid[12], tfstr[32], *dir;
1639 uint32_t i, seq, ack, server_isn, client_isn;
1640 uint16_t len, datalen;
1641 uint8_t proto, flags, iphlen, tcphlen;
1642 size_t tfoff;
1643
1644 printf("sting from %s to %s\n",
1645 scamper_addr_tostr(sting->src, src, sizeof(src)),
1646 scamper_addr_tostr(sting->dst, dst, sizeof(dst)));
1647
1648 dump_list_summary(sting->list);
1649 dump_cycle_summary(sting->cycle);
1650 printf(" user-id: %d\n", sting->userid);
1651 dump_timeval("start", &sting->start);
1652 printf(" sport: %d, dport: %d\n", sting->sport, sting->dport);
1653 printf(" count: %d, mean: %dus, inter: %dus, seqskip %d\n",
1654 sting->count, sting->mean, sting->inter, sting->seqskip);
1655 printf(" synretx: %d, dataretx: %d\n", sting->synretx, sting->dataretx);
1656 printf(" dataackc: %d, holec: %d\n", sting->dataackc, sting->holec);
1657 printf(" hs-rtt: %d.%06d\n",
1658 (int)sting->hsrtt.tv_sec, (int)sting->hsrtt.tv_usec);
1659
1660 printf(" result: ");
1661 if(sting->result == SCAMPER_STING_RESULT_NONE)
1662 printf("none");
1663 else if(sting->result == SCAMPER_STING_RESULT_COMPLETED)
1664 printf("completed");
1665 else
1666 printf("0x%02x", sting->result);
1667 printf("\n");
1668
1669 client_isn = 0;
1670 server_isn = 0;
1671
1672 for(i=0; i<sting->pktc; i++)
1673 {
1674 pkt = sting->pkts[i];
1675
1676 if((pkt->data[0] >> 4) == 4)
1677 {
1678 iphlen = (pkt->data[0] & 0xf) * 4;
1679 len = bytes_ntohs(pkt->data+2);
1680 proto = pkt->data[9];
1681 snprintf(ipid, sizeof(ipid), " %04x", bytes_ntohs(pkt->data+4));
1682 }
1683 else if((pkt->data[0] >> 4) == 6)
1684 {
1685 iphlen = 40;
1686 len = bytes_ntohs(pkt->data+4) + iphlen;
1687 proto = pkt->data[6];
1688 ipid[0] = '\0';
1689
1690 for(;;)
1691 {
1692 switch(proto)
1693 {
1694 case IPPROTO_HOPOPTS:
1695 case IPPROTO_DSTOPTS:
1696 case IPPROTO_ROUTING:
1697 if(pkt->data[iphlen+1] == 0 ||
1698 255 - iphlen <= (pkt->data[iphlen+1] * 8) + 8)
1699 break;
1700 proto = pkt->data[iphlen+0];
1701 iphlen += (pkt->data[iphlen+1] * 8) + 8;
1702 continue;
1703
1704 case IPPROTO_FRAGMENT:
1705 if(255 - iphlen <= 8)
1706 break;
1707 proto = pkt->data[iphlen+0];
1708 iphlen += 8;
1709 continue;
1710 }
1711 break;
1712 }
1713 }
1714 else continue;
1715
1716 if(proto != IPPROTO_TCP)
1717 continue;
1718
1719 timeval_diff_tv(&diff, &sting->start, &pkt->tv);
1720 if(pkt->flags & SCAMPER_STING_PKT_FLAG_TX) dir = "TX";
1721 else if(pkt->flags & SCAMPER_STING_PKT_FLAG_RX) dir = "RX";
1722 else dir = "??";
1723
1724 printf(" [%3d.%03d] %s ",(int)diff.tv_sec,(int)(diff.tv_usec/1000),dir);
1725
1726 seq = bytes_ntohl(pkt->data+iphlen+4);
1727 ack = bytes_ntohl(pkt->data+iphlen+8);
1728 flags = pkt->data[iphlen+13];
1729 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
1730
1731 tfoff = 0;
1732 if(flags & 0x2)
1733 {
1734 if(flags & 0x10)
1735 {
1736 server_isn = seq;
1737 string_concat(tfstr, sizeof(tfstr), &tfoff, "SYN/ACK");
1738 }
1739 else
1740 {
1741 client_isn = seq;
1742 string_concat(tfstr, sizeof(tfstr), &tfoff, "SYN");
1743 }
1744 }
1745 else if(flags & 0x1)
1746 string_concat(tfstr, sizeof(tfstr), &tfoff, "FIN");
1747 else if(flags & 0x4)
1748 string_concat(tfstr, sizeof(tfstr), &tfoff, "RST");
1749
1750 if(flags & 0x40)
1751 string_concat(tfstr, sizeof(tfstr), &tfoff, "%sECE",
1752 tfoff != 0 ? "/" : "");
1753 if(flags & 0x80)
1754 string_concat(tfstr, sizeof(tfstr), &tfoff, "%sCWR",
1755 tfoff != 0 ? "/" : "");
1756 if(tfoff == 0)
1757 tfstr[0] = '\0';
1758
1759 if(pkt->flags & SCAMPER_STING_PKT_FLAG_TX)
1760 {
1761 seq = tbit_isnoff(client_isn, seq);
1762 ack = tbit_isnoff(server_isn, ack);
1763 }
1764 else
1765 {
1766 seq = tbit_isnoff(server_isn, seq);
1767 ack = tbit_isnoff(client_isn, ack);
1768 }
1769
1770 datalen = len - iphlen - tcphlen;
1771
1772 printf("%-13s %4d", tfstr, len);
1773 if(datalen != 0)
1774 snprintf(buf, sizeof(buf), " seq = %u:%u(%d)", seq, ack, datalen);
1775 else
1776 snprintf(buf, sizeof(buf), " seq = %u:%u", seq, ack);
1777 printf("%-23s%s\n", buf, ipid);
1778 }
1779
1780 scamper_sting_free(sting);
1781 return;
1782 }
1783
dump_sniff(scamper_sniff_t * sniff)1784 static void dump_sniff(scamper_sniff_t *sniff)
1785 {
1786 scamper_sniff_pkt_t *pkt;
1787 struct timeval tv;
1788 uint8_t u8, *ptr;
1789 uint32_t i, j;
1790 int k;
1791 char src[64], dst[64], buf[32], *str;
1792
1793 printf("sniff %s\n", scamper_addr_tostr(sniff->src, src, sizeof(src)));
1794 dump_list_summary(sniff->list);
1795 dump_cycle_summary(sniff->cycle);
1796 printf(" user-id: %d\n", sniff->userid);
1797 dump_timeval("start", &sniff->start);
1798 dump_timeval("finish", &sniff->finish);
1799 printf(" limit-pktc: %d, limit-time: %d, icmp-id %d\n",
1800 sniff->limit_pktc, sniff->limit_time, sniff->icmpid);
1801 switch(sniff->stop_reason)
1802 {
1803 case SCAMPER_SNIFF_STOP_NONE: str = "none"; break;
1804 case SCAMPER_SNIFF_STOP_ERROR: str = "error"; break;
1805 case SCAMPER_SNIFF_STOP_LIMIT_TIME: str = "limit-time"; break;
1806 case SCAMPER_SNIFF_STOP_LIMIT_PKTC: str = "limit-pktc"; break;
1807 case SCAMPER_SNIFF_STOP_HALTED: str = "halted"; break;
1808 default:
1809 snprintf(buf, sizeof(buf), "%d", sniff->stop_reason);
1810 str = buf;
1811 break;
1812 }
1813 printf(" result: %s, pktc: %d\n", str, sniff->pktc);
1814
1815 for(i=0; i<sniff->pktc; i++)
1816 {
1817 pkt = sniff->pkts[i];
1818 timeval_diff_tv(&tv, &sniff->start, &pkt->tv);
1819 printf(" %3d %d.%06d", i, (int)tv.tv_sec, (int)tv.tv_usec);
1820 u8 = (pkt->data[0] & 0xf0) >> 4;
1821 if(u8 == 4)
1822 {
1823 printf(" %s -> %s",
1824 inet_ntop(AF_INET, pkt->data+12, src, sizeof(src)),
1825 inet_ntop(AF_INET, pkt->data+16, dst, sizeof(dst)));
1826 }
1827 else if(u8 == 6)
1828 {
1829 printf(" %s -> %s",
1830 inet_ntop(AF_INET6, pkt->data+8, src, sizeof(src)),
1831 inet_ntop(AF_INET6, pkt->data+24, dst, sizeof(dst)));
1832 }
1833 printf("\n");
1834
1835 ptr = pkt->data;
1836 for(j=0; j+16<=pkt->len; j+=16)
1837 {
1838 printf(" 0x%04x: ", j);
1839 for(k=0; k<8; k++)
1840 {
1841 printf(" %02x%02x", ptr[0], ptr[1]);
1842 ptr += 2;
1843 }
1844 printf("\n");
1845 }
1846 if(pkt->len - j != 0)
1847 {
1848 printf(" 0x%04x: ", j);
1849 while(j<pkt->len)
1850 {
1851 if((j % 2) == 0)
1852 printf(" ");
1853 printf("%02x", *ptr);
1854 ptr++;
1855 j++;
1856 }
1857 printf("\n");
1858 }
1859 }
1860
1861 return;
1862 }
1863
dump_host_rr(scamper_host_rr_t * rr,const char * section)1864 static void dump_host_rr(scamper_host_rr_t *rr, const char *section)
1865 {
1866 char buf[256];
1867
1868 printf(" %s: %s %u ", section,
1869 rr->name != NULL ? rr->name : "<null>", rr->ttl);
1870
1871 if(rr->class == SCAMPER_HOST_CLASS_IN)
1872 printf("IN");
1873 else
1874 printf("%d", rr->class);
1875 printf(" ");
1876 switch(rr->type)
1877 {
1878 case SCAMPER_HOST_TYPE_A: printf("A"); break;
1879 case SCAMPER_HOST_TYPE_NS: printf("NS"); break;
1880 case SCAMPER_HOST_TYPE_CNAME: printf("CNAME"); break;
1881 case SCAMPER_HOST_TYPE_SOA: printf("SOA"); break;
1882 case SCAMPER_HOST_TYPE_PTR: printf("PTR"); break;
1883 case SCAMPER_HOST_TYPE_MX: printf("MX"); break;
1884 case SCAMPER_HOST_TYPE_TXT: printf("TXT"); break;
1885 case SCAMPER_HOST_TYPE_AAAA: printf("AAAA"); break;
1886 case SCAMPER_HOST_TYPE_DS: printf("DS"); break;
1887 case SCAMPER_HOST_TYPE_SSHFP: printf("SSHFP"); break;
1888 case SCAMPER_HOST_TYPE_RRSIG: printf("RRISG"); break;
1889 case SCAMPER_HOST_TYPE_NSEC: printf("NSEC"); break;
1890 case SCAMPER_HOST_TYPE_DNSKEY: printf("DNSKEY"); break;
1891 default: printf("%d", rr->type); break;
1892 }
1893
1894 switch(scamper_host_rr_data_type(rr->class, rr->type))
1895 {
1896 case SCAMPER_HOST_RR_DATA_TYPE_ADDR:
1897 printf(" %s", scamper_addr_tostr(rr->un.addr, buf, sizeof(buf)));
1898 break;
1899
1900 case SCAMPER_HOST_RR_DATA_TYPE_STR:
1901 printf(" %s", rr->un.str);
1902 break;
1903
1904 case SCAMPER_HOST_RR_DATA_TYPE_MX:
1905 printf(" %d %s", rr->un.mx->preference, rr->un.mx->exchange);
1906 break;
1907 }
1908
1909 printf("\n");
1910 return;
1911 }
1912
dump_host(scamper_host_t * host)1913 static void dump_host(scamper_host_t *host)
1914 {
1915 scamper_host_query_t *query;
1916 struct timeval tv;
1917 char buf[256];
1918 uint32_t i, j;
1919
1920 printf("host");
1921 if(host->src != NULL)
1922 printf(" from %s", scamper_addr_tostr(host->src, buf, sizeof(buf)));
1923 printf(" to %s\n", scamper_addr_tostr(host->dst, buf, sizeof(buf)));
1924 dump_list_summary(host->list);
1925 dump_cycle_summary(host->cycle);
1926 printf(" user-id: %d\n", host->userid);
1927 dump_timeval("start", &host->start);
1928
1929 if(host->flags != 0)
1930 {
1931 printf(" flags: ");
1932 if(host->flags & SCAMPER_HOST_FLAG_NORECURSE)
1933 printf("norecurse");
1934 printf("\n");
1935 }
1936
1937 printf(" wait: %ums, retries: %u\n", host->wait, host->retries);
1938 printf(" stop: ");
1939 switch(host->stop)
1940 {
1941 case SCAMPER_HOST_STOP_NONE: printf("none"); break;
1942 case SCAMPER_HOST_STOP_DONE: printf("done"); break;
1943 case SCAMPER_HOST_STOP_TIMEOUT: printf("timeout"); break;
1944 case SCAMPER_HOST_STOP_HALTED: printf("halted"); break;
1945 case SCAMPER_HOST_STOP_ERROR: printf("error"); break;
1946 default: printf("%04x", host->stop); break;
1947 }
1948 printf("\n");
1949
1950 printf(" qname: %s, qclass: ", host->qname);
1951 if(host->qclass == SCAMPER_HOST_CLASS_IN)
1952 printf("IN");
1953 else
1954 printf("%d", host->qclass);
1955
1956 printf(", qtype: ");
1957 switch(host->qtype)
1958 {
1959 case SCAMPER_HOST_TYPE_A: printf("A"); break;
1960 case SCAMPER_HOST_TYPE_NS: printf("NS"); break;
1961 case SCAMPER_HOST_TYPE_CNAME: printf("CNAME"); break;
1962 case SCAMPER_HOST_TYPE_SOA: printf("SOA"); break;
1963 case SCAMPER_HOST_TYPE_PTR: printf("PTR"); break;
1964 case SCAMPER_HOST_TYPE_MX: printf("MX"); break;
1965 case SCAMPER_HOST_TYPE_TXT: printf("TXT"); break;
1966 case SCAMPER_HOST_TYPE_AAAA: printf("AAAA"); break;
1967 case SCAMPER_HOST_TYPE_DS: printf("DS"); break;
1968 case SCAMPER_HOST_TYPE_SSHFP: printf("SSHFP"); break;
1969 case SCAMPER_HOST_TYPE_RRSIG: printf("RRSIG"); break;
1970 case SCAMPER_HOST_TYPE_NSEC: printf("NSEC"); break;
1971 case SCAMPER_HOST_TYPE_DNSKEY: printf("DNSKEY"); break;
1972 default: printf("%04x", host->qtype); break;
1973 }
1974 printf("\n");
1975 printf(" qcount: %d\n", host->qcount);
1976
1977 for(i=0; i<host->qcount; i++)
1978 {
1979 query = host->queries[i];
1980 timeval_diff_tv(&tv, &host->start, &query->tx);
1981 printf(" query: %u, id: %u, tx: %d.%06d", i, query->id,
1982 (int)tv.tv_sec, (int)tv.tv_usec);
1983 timeval_diff_tv(&tv, &query->tx, &query->rx);
1984 printf(", rtt: %d.%06d", (int)tv.tv_sec, (int)tv.tv_usec);
1985 printf(", an: %u, ns: %u, ar: %u", query->ancount, query->nscount,
1986 query->arcount);
1987 printf("\n");
1988
1989 for(j=0; j<query->ancount; j++)
1990 dump_host_rr(query->an[j], "an");
1991 for(j=0; j<query->nscount; j++)
1992 dump_host_rr(query->ns[j], "ns");
1993 for(j=0; j<query->arcount; j++)
1994 dump_host_rr(query->ar[j], "ar");
1995 }
1996
1997 printf("\n");
1998 return;
1999 }
2000
dump_cycle(scamper_cycle_t * cycle,const char * type)2001 static void dump_cycle(scamper_cycle_t *cycle, const char *type)
2002 {
2003 time_t tt;
2004 char buf[32];
2005
2006 if(strcmp(type, "start") == 0 || strcmp(type, "def") == 0)
2007 tt = cycle->start_time;
2008 else
2009 tt = cycle->stop_time;
2010
2011 memcpy(buf, ctime(&tt), 24); buf[24] = '\0';
2012
2013 printf("cycle %s, list %s %d, cycle %d, time %s\n",
2014 type, cycle->list->name, cycle->list->id, cycle->id, buf);
2015 scamper_cycle_free(cycle);
2016 return;
2017 }
2018
dump_list(scamper_list_t * list)2019 static void dump_list(scamper_list_t *list)
2020 {
2021 printf("list id %d, name %s", list->id, list->name);
2022 if(list->descr != NULL) printf(", descr \"%s\"", list->descr);
2023 printf("\n");
2024 scamper_list_free(list);
2025 return;
2026 }
2027
dump_addr(scamper_addr_t * addr)2028 static void dump_addr(scamper_addr_t *addr)
2029 {
2030 char buf[128];
2031 printf("addr %s\n", scamper_addr_tostr(addr, buf, sizeof(buf)));
2032 scamper_addr_free(addr);
2033 return;
2034 }
2035
main(int argc,char * argv[])2036 int main(int argc, char *argv[])
2037 {
2038 scamper_file_t *file;
2039 scamper_file_filter_t *filter;
2040 uint16_t filter_types[] = {
2041 SCAMPER_FILE_OBJ_LIST,
2042 SCAMPER_FILE_OBJ_CYCLE_START,
2043 SCAMPER_FILE_OBJ_CYCLE_DEF,
2044 SCAMPER_FILE_OBJ_CYCLE_STOP,
2045 SCAMPER_FILE_OBJ_TRACE,
2046 SCAMPER_FILE_OBJ_PING,
2047 SCAMPER_FILE_OBJ_TRACELB,
2048 SCAMPER_FILE_OBJ_DEALIAS,
2049 SCAMPER_FILE_OBJ_NEIGHBOURDISC,
2050 SCAMPER_FILE_OBJ_TBIT,
2051 SCAMPER_FILE_OBJ_STING,
2052 SCAMPER_FILE_OBJ_SNIFF,
2053 SCAMPER_FILE_OBJ_HOST,
2054 };
2055 uint16_t filter_cnt = sizeof(filter_types)/sizeof(uint16_t);
2056 void *data;
2057 uint16_t type;
2058 int f;
2059
2060 #ifdef _WIN32
2061 WSADATA wsaData;
2062 WSAStartup(MAKEWORD(2,2), &wsaData);
2063 #endif
2064
2065 #if defined(DMALLOC)
2066 free(malloc(1));
2067 #endif
2068
2069 if((filter = scamper_file_filter_alloc(filter_types, filter_cnt)) == NULL)
2070 {
2071 usage();
2072 fprintf(stderr, "could not alloc filter\n");
2073 return -1;
2074 }
2075
2076 for(f=0; f<argc; f++)
2077 {
2078 if(f == 0)
2079 {
2080 if(argc > 1)
2081 continue;
2082
2083 if((file=scamper_file_openfd(STDIN_FILENO,"-",'r',"warts")) == NULL)
2084 {
2085 usage();
2086 fprintf(stderr, "could not use stdin\n");
2087 return -1;
2088 }
2089 }
2090 else
2091 {
2092 if((file = scamper_file_open(argv[f], 'r', NULL)) == NULL)
2093 {
2094 usage();
2095 fprintf(stderr, "could not open %s\n", argv[f]);
2096 return -1;
2097 }
2098 }
2099
2100 while(scamper_file_read(file, filter, &type, &data) == 0)
2101 {
2102 /* hit eof */
2103 if(data == NULL)
2104 goto done;
2105
2106 switch(type)
2107 {
2108 case SCAMPER_FILE_OBJ_ADDR:
2109 dump_addr(data);
2110 break;
2111
2112 case SCAMPER_FILE_OBJ_TRACE:
2113 dump_trace(data);
2114 break;
2115
2116 case SCAMPER_FILE_OBJ_PING:
2117 dump_ping(data);
2118 break;
2119
2120 case SCAMPER_FILE_OBJ_TRACELB:
2121 dump_tracelb(data);
2122 break;
2123
2124 case SCAMPER_FILE_OBJ_DEALIAS:
2125 dump_dealias(data);
2126 break;
2127
2128 case SCAMPER_FILE_OBJ_NEIGHBOURDISC:
2129 dump_neighbourdisc(data);
2130 break;
2131
2132 case SCAMPER_FILE_OBJ_TBIT:
2133 dump_tbit(data);
2134 break;
2135
2136 case SCAMPER_FILE_OBJ_STING:
2137 dump_sting(data);
2138 break;
2139
2140 case SCAMPER_FILE_OBJ_SNIFF:
2141 dump_sniff(data);
2142 break;
2143
2144 case SCAMPER_FILE_OBJ_HOST:
2145 dump_host(data);
2146 break;
2147
2148 case SCAMPER_FILE_OBJ_LIST:
2149 dump_list(data);
2150 break;
2151
2152 case SCAMPER_FILE_OBJ_CYCLE_START:
2153 dump_cycle(data, "start");
2154 break;
2155
2156 case SCAMPER_FILE_OBJ_CYCLE_STOP:
2157 dump_cycle(data, "stop");
2158 break;
2159
2160 case SCAMPER_FILE_OBJ_CYCLE_DEF:
2161 dump_cycle(data, "def");
2162 break;
2163 }
2164 }
2165
2166 done:
2167 scamper_file_close(file);
2168
2169 if(argc == 1)
2170 break;
2171 }
2172
2173 scamper_file_filter_free(filter);
2174 return 0;
2175 }
2176