1 /*
2 * lft_lib.c
3 * Layer Four Traceroute
4 *
5 * This file is part of LFT.
6 *
7 * The LFT software provided in this Distribution is
8 * Copyright 2010 VOSTROM Holdings, Inc.
9 *
10 * The full text of our legal notices is contained in the file called
11 * COPYING, included with this Distribution.
12 *
13 */
14
15 #define _USE_32BIT_TIME_T
16
17 #include "lft_lib.h"
18 #include "lft_btcptrace.h"
19 #include "lft_icmptrace.h"
20
21 /*---------------------------------------------------------------------------*/
22 /* GraphViz output defines */
23 #define GVGRAPHNAME "lftpath"
24 /*
25 #define GVHOPSTYLE_BASE "shape = rect, penwidth=1"
26 #define GVHOPSTYLE_SOURCE "shape = rect, style=filled, fillcolor=lightskyblue, color=skyblue, penwidth=2"
27 #define GVHOPSTYLE_TARGET_OPEN "shape = rect, style=filled, fillcolor=palegreen, color=mediumspringgreen, penwidth=2"
28 #define GVHOPSTYLE_TARGET_CLOSED "shape = rect, style=filled, fillcolor=tomato, color=orangered, penwidth=2"
29 #define GVHOPSTYLE_TARGET_FILTERED "shape = rect, style=filled, fillcolor=grey, color=mediumspringgreen, penwidth=2"
30 #define GVHOPSTYLE_HOLE "shape = note, style=filled, fillcolor=lightgrey, color=slategrey, penwidth=2"
31 #define GVHOPSTYLE_ANOMALY1 "shape = rect, style=filled, fillcolor=salmon, skew=.4, color=orangered, penwidth=2"
32 #define GVHOPSTYLE_ANOMALY2 "shape = rect, style=filled, fillcolor=lemonchiffon, skew=.4, color=orangered, penwidth=2"
33 #define GVHOPSTYLE_ANOMALY3 "shape = rect, style=filled, fillcolor=lightgrey, color=slategrey, skew=.4, penwidth=2"
34 */
35 #define GVHOPSTYLE_BASE "shape = none"
36 #define GVHOPSTYLE_SOURCE "shape = none"
37 #define GVHOPSTYLE_TARGET_OPEN "shape = none"
38 #define GVHOPSTYLE_TARGET_CLOSED "shape = none"
39 #define GVHOPSTYLE_TARGET_FILTERED "shape = none"
40 #define GVHOPSTYLE_HOLE "shape = none"
41 /* Firewall - The next gateway may statefully inspect packets */
42 #define GVHOPSTYLE_ANOMALY1 "shape = none"
43 /* Firewall - The next gateway may implement a flag-based state filter */
44 #define GVHOPSTYLE_ANOMALY2 "shape = none"
45 /* 4.2-3 BSD bug - The next gateway may errantly reply with reused TTLs */
46 #define GVHOPSTYLE_ANOMALY3 "shape = none"
47
48 #define GV_ANOMALY1_TEXT "Stateful Firewall"
49 #define GV_ANOMALY2_TEXT "Flag-based Firewall"
50 #define GV_ANOMALY3_TEXT "BSD-stack TTL Reused"
51
52 #define GVFONTSIZE "12"
53 #define GVFONTNAME "Helvetica"
54
55 static const char GVNTBEG[]="<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><img src=\"";
56 static const char GVNTMID[]="\"/></td></tr><tr><td>";
57 static const char GVNTEND[]="</td></tr></table>";
58 static const char GVNIMG_SOURCE[]="source.png";
59 static const char GVNIMG_TRGOPEN[]="dest.png";
60 static const char GVNIMG_TRGCLOSED[]="dest_closed.png";
61 static const char GVNIMG_TRGFILTERED[]="dest_prohibited.png";
62 static const char GVNIMG_ANOMALY1[]="firewall_smart.png";
63 static const char GVNIMG_ANOMALY2[]="firewall_stupid.png";
64 static const char GVNIMG_ANOMALY3[]="firewall_stupid.png";
65 static const char GVNIMG_REGULAR[]="router.png";
66 static const char GVNIMG_HOLE[]="router_cloaked.png";
67 static const char GVNIMG_SEAM[]="router_seam.png";
68 #if defined(WIN32) || defined(_WIN32)
69 static const char DIRECTORY_SPLITTER='\\';
70 #else
71 static const char DIRECTORY_SPLITTER='/';
72 #endif
73 /*---------------------------------------------------------------------------*/
74 static const int start_dport = 33434; /* starting port for UDP tracing (traceroute
75 compatibility for some targets that care */
76 const int maxpacklen = 16 * 1024; /* maximum user-supplied probe length */
77 /* Ethernet=1500, GigEther(jumbo)=9000 */
78 static const int minpacklen = 60; /* minimum user-supplied probe length */
79
80 const char * icmp_messages[] = {
81 "endpoint",
82 "net unreachable",
83 "host unreachable",
84 "protocol unreachable",
85 "port unreachable",
86 "need fragment",
87 "source fail",
88 "net unknown",
89 "host unknown",
90 "src isolated",
91 "net prohib",
92 "host prohib",
93 "bad tos/net",
94 "bad tos/hst",
95 "prohibited",
96 "precedence violation",
97 "precedence cutoff"
98 };
99
100 static char time_format[] = "%d-%b-%y %H:%M:%S %Z"; /* time display format */
101 static char tbuf[128];
102 const char *appname = "LFT";
103 static const int hop_info_size = 256; /* can't be more than this */
104
105 static const unsigned int max_net_dev_input = 64; /* only take this much input */
106
107 static const int def_payload_len = 10; /* default payload length for UDP packets */
108
109 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
110 static int sock = -1;
111 #endif
112
113 static int global_output_style=0; /* 0 - ordinary output, 1 - xml output, 2 - GraphViz output */
114
115 void GraphVizOutput(lft_session_params * sess);
116
117 /*---------------------------------------------------------------------------*/
LFTDefaultErrorHandler(lft_session_params * sess,int code,const void * params)118 static void LFTDefaultErrorHandler(lft_session_params * sess, int code, const void * params)
119 {
120 const WrnBadHopStateParam * wbhsp;
121 switch(code)
122 {
123 case WRN_CANT_SETUP_FIN:
124 if(global_output_style==1)
125 printf("<warning code=\"%d\">%s</warning>",code,
126 "TCP flags are selected automatically using (-E) option.\n\t\t\tIgnoring FINs-only (-F) option and using adaptive Engine.\n");
127 else
128 fprintf (stderr,
129 "LFT warning: TCP flags are selected automatically using (-E) option.\n\t\t\tIgnoring FINs-only (-F) option and using adaptive Engine.\n");
130 break;
131 case WRN_CANT_DISP_HOST_NAMES:
132 if(global_output_style==1)
133 printf("<warning code=\"%d\">%s</warning>",code,
134 "I can't display hostnames (-h) unless I resolve them.\n\t\t\tIgnoring your request to display hostnames exclusively.\n");
135 else
136 fprintf (stderr,
137 "LFT warning: I can't display hostnames (-h) unless I resolve them.\n\t\t\tIgnoring your request to display hostnames exclusively.\n");
138 break;
139 case WRN_ADAPTIVE_DISABLED_BY_UDP:
140 if(global_output_style==1)
141 printf("<warning code=\"%d\">%s</warning>",code,"Disabling adaptive mode while using UDP.");
142 else
143 fprintf (stderr,"LFT warning: Disabling adaptive mode while using UDP.\n");
144 break;
145 case WRN_FIN_DISABLED_BY_UDP:
146 if(global_output_style==1)
147 printf("<warning code=\"%d\">%s</warning>",code,"Disabling FINs-only mode while using UDP.");
148 else
149 fprintf (stderr,"LFT warning: Disabling FINs-only mode while using UDP.\n");
150 break;
151 case WRN_ONLY_ONE_ASN_LOOKUP:
152 if(global_output_style==1)
153 printf("<warning code=\"%d\">%s",code,"Only one ASN lookup source may be used--you selected ");
154 else
155 fprintf (stderr,"LFT warning: Only one ASN lookup source may be used--you selected ");
156 if(global_output_style!=1)
157 {
158 if(sess->use_cymru)
159 fprintf (stderr,"Cymru.\n\t\t\tIgnoring your request to use ");
160 if(sess->use_ris)
161 fprintf (stderr,"RIPE NCC RIS.\n\t\t\tIgnoring your request to use ");
162 if(sess->use_radb)
163 fprintf (stderr,"RADB.\n\t\t\tIgnoring your request to use ");
164 switch(*((const int *)params))
165 {
166 case ASN_LOOKUP_RIS:
167 fprintf (stderr,"RIPE NCC RIS.\n");
168 break;
169 case ASN_LOOKUP_RADB:
170 fprintf (stderr,"RADB.\n");
171 break;
172 case ASN_LOOKUP_CYMRU:
173 fprintf (stderr,"Cymru.\n");
174 break;
175 }
176 if(global_output_style==1)
177 printf("</warning>");
178 }
179 break;
180 case WRN_UDP_PORT_TOO_HIGH:
181 if(global_output_style==1)
182 printf("<warning code=\"%d\">Starting UDP port %d is too high. Will start with %d instead.</warning>",
183 code, *((const int *)params), sess->dport);
184 else
185 fprintf (stderr,
186 "LFT warning: Starting UDP port %d is too high. Will start with %d instead.\n", *((const int *)params), sess->dport);
187 break;
188 case WRN_PACKET_LENGTH_TOO_HIGH:
189 if(global_output_style==1)
190 printf("<warning code=\"%d\">Packet length %d is too high. Will use %d instead.</warning>",
191 code, *((const int *)params), maxpacklen);
192 else
193 fprintf (stderr,
194 "LFT warning: Packet length %d is too high. Will use %d instead.\n", *((const int *)params), maxpacklen);
195 break;
196 case WRN_PACKET_LENGTH_TOO_LOW:
197 if(global_output_style==1)
198 printf("<warning code=\"%d\">Packet length %d is too low. Will use %d instead.</warning>",
199 code, *((const int *)params), minpacklen);
200 else
201 fprintf (stderr,
202 "LFT warning: Packet length %d is too low. Will use %d instead.\n", *((const int *)params), minpacklen);
203 break;
204 case WRN_CANT_DISABLE_RESOLVER:
205 if(global_output_style==1)
206 printf("<warning code=\"%d\">%s</warning>",code,
207 "LFT warning: I can't display hostnames (-h) unless I resolve them.\n\t\t\tIgnoring your request not to resolve DNS.\n");
208 else
209 fprintf (stderr,
210 "LFT warning: I can't display hostnames (-h) unless I resolve them.\n\t\t\tIgnoring your request not to resolve DNS.\n");
211 break;
212 case WRN_ALREADY_RANDOM_SPORT:
213 if(global_output_style==1)
214 printf("<warning code=\"%d\">%s</warning>",code,
215 "LFT warning: You already asked to use a random source port.\n\t\t\tIgnoring request to set specific source port.\n");
216 else
217 fprintf (stderr,
218 "LFT warning: You already asked to use a random source port.\n\t\t\tIgnoring request to set specific source port.\n");
219 break;
220 case WRN_ADAPTIVE_DISABLED_BY_FIN:
221 if(global_output_style==1)
222 printf("<warning code=\"%d\">%s</warning>",code,
223 "LFT warning: TCP flags are selected automatically using (-E) option.\n\t\t\tIgnoring adaptive Engine (-E) option and using FINs-only (-F).\n");
224 else
225 fprintf (stderr,
226 "LFT warning: TCP flags are selected automatically using (-E) option.\n\t\t\tIgnoring adaptive Engine (-E) option and using FINs-only (-F).\n");
227 break;
228 case ERR_DEVNAME_TOO_LONG:
229 if(global_output_style==1)
230 printf("<error code=\"%d\">Net interface names are limited to %d characters. (e.g., \"eth0\" or \"ppp0\" or \"10.10.10.10\")</error>",code,
231 max_net_dev_input);
232 else
233 fprintf (stderr,
234 "Net interface names are limited to %d characters. (e.g., \"eth0\" or \"ppp0\" or \"10.10.10.10\")\n",
235 max_net_dev_input);
236 sess->exit_state=-1;
237 break;
238 case WRN_UNABLE_SETUP_UTC:
239 if(global_output_style==1)
240 printf("<warning code=\"%d\">%s</warning>",code,"Unable to set TZ to UTC.");
241 else
242 fprintf(stderr, "LFT: Unable to set TZ to UTC.\n");
243 break;
244 case ERR_UNKNOWN_HOST:
245 if(global_output_style==1)
246 printf("<error code=\"%d\">Unknown host: %s</error>",code,(const char *)params);
247 else
248 fprintf (stderr, "LFT: Unknown host: %s\n", (const char *)params);
249 sess->exit_state=-2;
250 break;
251 case WRN_GETIFFORREMOTE_SOCKET:
252 if(global_output_style==1)
253 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
254 printf("<warning code=\"%d\">socket: %s</warning>",code,strerror(errno));
255 #else
256 printf("<warning code=\"%d\">Socket trouble; unable to determine interface</warning>",code);
257 #endif
258 else
259 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
260 perror("socket");
261 #else
262 perror("LFT: Socket trouble; unable to determine interface");
263 #endif
264 break;
265 case WRN_GETIFFORREMOTE_CONNECT:
266 if(global_output_style==1)
267 printf("<warning code=\"%d\">UDP connect(); unable to determine interface: %s</warning>",code,strerror(errno));
268 else
269 perror("LFT: UDP connect(); unable to determine interface");
270 break;
271 case WRN_GETIFFORREMOTE_SOCKNAME:
272 if(global_output_style==1)
273 printf("<warning code=\"%d\">getsockname: %s</warning>",code,strerror(errno));
274 else
275 perror("getsockname");
276 break;
277 case ERR_RAW_SOCKET:
278 if(global_output_style==1)
279 printf("<error code=\"%d\">raw socket: %s</error>",code,strerror(errno));
280 else
281 perror ("LFT: raw socket");
282 sess->exit_state=-3;
283 break;
284 case ERR_SOCKET_BIND:
285 if(global_output_style==1)
286 printf("<error code=\"%d\">bind: %s</error>",code,strerror(errno));
287 else
288 perror ("LFT: bind");
289 sess->exit_state=-4;
290 break;
291 case WRN_WSAIOCTL:
292 if(global_output_style==1)
293 printf("<warning code=\"%d\">WSAIoctl: %s</warning>",code,strerror(errno));
294 else
295 perror("LFT: WSAIoctl");
296 break;
297 case ERR_IP_HDRINCL:
298 if(global_output_style==1)
299 printf("<error code=\"%d\">IP_HDRINCL: %s</error>",code,strerror(errno));
300 else
301 perror ("LFT: IP_HDRINCL");
302 sess->exit_state=-5;
303 break;
304 case ERR_NOT_ENOUGH_MEM:
305 if(global_output_style==1)
306 printf("<error code=\"%d\">malloc(): %s</error>",code,strerror(errno));
307 else
308 perror("malloc");
309 sess->exit_state=-6;
310 break;
311 case ERR_RAW_TCP_DISABLED:
312 if(global_output_style==1)
313 {
314 printf("<error code=\"%d\">sendto: %s\n",code,strerror(errno));
315 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
316 if (!sess->protocol) {
317 printf("Your platform may prevent you from using raw TCP sockets.\n");
318 printf("Try UDP-based tracing instead using the \"-u\" option.\n");
319 }
320 #else
321 printf("Your platform may prevent you from using raw TCP sockets.\n");
322 printf("This could be the result of a local (host-based) firewall\n");
323 printf("or a permissions problem on this binary or the BPF device.\n");
324 if(sess->adaptive)
325 printf("You can try TCP-based tracing without using adaptive mode.\n");
326 printf("You can try UDP-based tracing using the \"-u\" option.\n");
327 #endif
328 printf("</error>\n");
329 }
330 else
331 {
332 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
333 perror ("sendto");
334 if (!sess->protocol) {
335 fprintf(stderr,"LFT: Your platform may prevent you from using raw TCP sockets.\n");
336 fprintf(stderr," Try UDP-based tracing instead using the \"-u\" option.\n");
337 }
338 #else
339 perror ("sendto");
340 fprintf(stderr,"LFT: Your platform may prevent you from using raw TCP sockets.\n");
341 fprintf(stderr," This could be the result of a local (host-based) firewall\n");
342 fprintf(stderr," or a permissions problem on this binary or the BPF device.\n");
343 if (sess->adaptive)
344 fprintf(stderr," You can try TCP-based tracing without using adaptive mode.\n");
345 fprintf(stderr," You can try UDP-based tracing using the \"-u\" option.\n");
346 #endif
347 }
348 sess->exit_state=-7;
349 break;
350 case WRN_BAD_HOP_STATE:
351 wbhsp=(const WrnBadHopStateParam *)params;
352 if(global_output_style==1)
353 printf("<warning code=\"%d\">Bad state %#x for hop %d</warning>", code, wbhsp->h->state, wbhsp->nhop);
354 else
355 fprintf(stderr,"Bad state %#x for hop %d\n", wbhsp->h->state, wbhsp->nhop);
356 break;
357 case WRN_NS_LOOKUP_FAILED:
358 if(global_output_style==1)
359 {
360 printf("<warning code=\"%d\">", code);
361 if(sess->use_radb)
362 printf ("The RADB lookup failed.");
363 else
364 if(sess->use_cymru)
365 printf ("The Cymru lookup failed.");
366 else
367 if(sess->use_ris)
368 printf ("The RIPE NCC RIS lookup failed.");
369 else
370 printf ("The Prefix WhoIs lookup failed.");
371 printf("</warning>");
372 }
373 else
374 {
375 if(sess->use_radb)
376 fprintf(stderr,"The RADB lookup failed.\n");
377 else
378 if(sess->use_cymru)
379 fprintf(stderr,"The Cymru lookup failed.\n");
380 else
381 if(sess->use_ris)
382 fprintf(stderr,"The RIPE NCC RIS lookup failed.\n");
383 else
384 fprintf(stderr,"The Prefix WhoIs lookup failed.\n");
385 }
386 break;
387 case ERR_WIN_SELECT:
388 if(global_output_style==1)
389 printf("<error code=\"%d\">select: %s</error>",code,strerror(errno));
390 else
391 perror("select");
392 sess->exit_state=-8;
393 break;
394 case ERR_WIN_RECV:
395 if(global_output_style==1)
396 printf("<error code=\"%d\">read: %s</error>",code,strerror(errno));
397 else
398 perror("read");
399 sess->exit_state=-9;
400 break;
401 case ERR_WIN_WSASTARTUP:
402 if(global_output_style==1)
403 printf("<error code=\"%d\">WSAStartup: %s</error>",code,strerror(errno));
404 else
405 perror("WSAStartup");
406 sess->exit_state=-10;
407 break;
408 case ERR_PCAP_ERROR:
409 if(global_output_style==1)
410 printf("<error code=\"%d\">%s</error>",code,(const char *)params);
411 else
412 fprintf (stderr, "LFT: %s\n", (const char *)params);
413 sess->exit_state=-11;
414 break;
415 case ERR_DISCOVER_INTERFACE:
416 if(global_output_style==1)
417 printf("<error code=\"%d\">Failed to discover an appropriate interface</error>",code);
418 else
419 fprintf (stderr, "LFT: Failed to discover an appropriate interface.\n");
420 sess->exit_state=-12;
421 break;
422 case ERR_UNKNOWN_INTERFACE:
423 if(global_output_style==1)
424 printf("<error code=\"%d\">Unable to locate a local interface with IP address %s</error>",code,sess->userdev);
425 else
426 fprintf (stderr, "LFT: Unable to locate a local interface with IP address %s\n", sess->userdev);
427 sess->exit_state=-13;
428 break;
429 case ERR_PCAP_DEV_UNAVAILABLE:
430 if(global_output_style==1)
431 printf("<error code=\"%d\">The network device \"%s\" isn\'t available to LFT. Try another or fix:\nERROR: %s</error>",code,sess->pcap_dev,(const char *)params);
432 else
433 fprintf (stderr, "The network device \"%s\" isn\'t available to LFT. Try another or fix:\nERROR: %s\n", sess->pcap_dev, (const char *)params);
434 sess->exit_state=-14;
435 break;
436 case WRN_BIOCIMMEDIATE:
437 if(global_output_style==1)
438 printf("<warning code=\"%d\">BIOCIMMEDIATE: %s</warning>", code, (const char *)params);
439 else
440 fprintf(stderr, "BIOCIMMEDIATE: %s\n",(const char *)params);
441 sess->exit_state=-34;
442 break;
443 case WRN_OCHECK_OPEN_SOCK:
444 if(global_output_style!=1 && sess->noisy>1)
445 fprintf(stderr, "LFT: Error opening socket.\n");
446 if(global_output_style==1)
447 printf("<warning code=\"%d\">Error opening socket</warning>", code);
448 break;
449 case WRN_OCHECK_IOCTL:
450 if(global_output_style!=1 && sess->noisy>1)
451 fprintf(stderr, "LFT: Error setting nonblocking mode (IOCTL).\n");
452 if(global_output_style==1)
453 printf("<warning code=\"%d\">Error setting nonblocking mode (IOCTL)</warning>", code);
454 break;
455 case WRN_OCHECK_SELECT:
456 if(global_output_style!=1 && sess->noisy>1)
457 fprintf(stderr, "LFT: Error on socket select call.\n");
458 if(global_output_style==1)
459 printf("<warning code=\"%d\">Error on socket select call</warning>", code);
460 break;
461 case WRN_OCHECK_GETERROR:
462 if(global_output_style!=1 && sess->noisy>1)
463 fprintf(stderr, "LFT: Error trying to read socket error.\n");
464 if(global_output_style==1)
465 printf("<warning code=\"%d\">Error trying to read socket error</warning>", code);
466 break;
467 case WRN_OCHECK_SOCKERROR:
468 if(global_output_style!=1 && sess->noisy>1)
469 fprintf(stderr, "LFT: Error on socket.\n");
470 if(global_output_style==1)
471 printf("<warning code=\"%d\">Error on socket</warning>", code);
472 break;
473 case WRN_OCHECK_TIMEOUT:
474 if(global_output_style!=1 && sess->noisy>1)
475 fprintf(stderr, "LFT: Timeout on socket.\n");
476 if(global_output_style==1)
477 printf("<warning code=\"%d\">Timeout on socket</warning>", code);
478 break;
479 case WRN_OCHECK_FCNTLGET:
480 if(global_output_style!=1 && sess->noisy>1)
481 fprintf(stderr, "LFT: Error setting nonblocking mode (FCNTL GET).\n");
482 if(global_output_style==1)
483 printf("<warning code=\"%d\">Error setting nonblocking mode (FCNTL GET)</warning>", code);
484 break;
485 case WRN_OCHECK_FCNTLSET:
486 if(global_output_style!=1 && sess->noisy>1)
487 fprintf(stderr, "LFT: Error setting nonblocking mode (FCNTL SET).\n");
488 if(global_output_style==1)
489 printf("<warning code=\"%d\">Error setting nonblocking mode (FCNTL SET)</warning>", code);
490 break;
491 case WRN_OCHECK_CONNECTERR:
492 if(global_output_style!=1 && sess->noisy>1)
493 fprintf(stderr, "LFT: Error trying socket connect.\n");
494 if(global_output_style==1)
495 printf("<warning code=\"%d\">Error trying socket connect</warning>", code);
496 break;
497 case ERR_PCAP_NONBLOCK_ERROR:
498 if(global_output_style==1)
499 printf("<error code=\"%d\">%s</error>",code,(const char *)params);
500 else
501 fprintf (stderr, "LFT: Failed to set nonblocking mode.\n %s\n", (const char *)params);
502 sess->exit_state=-35;
503 break;
504 }
505 }
506 /*---------------------------------------------------------------------------*/
507 static void
print_host(lft_session_params * sess,struct in_addr addr)508 print_host (lft_session_params * sess, struct in_addr addr)
509 {
510 struct hostent *h;
511
512 if (!sess->resolve_names) {
513 if(global_output_style==1)
514 printf (" ip=\"%s\"", inet_ntoa (addr));
515 else
516 printf ("%s", inet_ntoa (addr));
517 } else {
518 h = gethostbyaddr ((void *) &addr, 4, AF_INET);
519 if (h) {
520 if(global_output_style==1)
521 printf (" host=\"%s\"", h->h_name);
522 else
523 printf ("%s", h->h_name);
524 if (!sess->hostnames_only)
525 {
526 if(global_output_style==1)
527 printf (" ip=\"%s\"", inet_ntoa (addr));
528 else
529 printf(" (%s)", inet_ntoa (addr));
530 }
531 } else
532 {
533 if(global_output_style==1)
534 printf (" ip=\"%s\"", inet_ntoa (addr));
535 else
536 printf ("%s", inet_ntoa (addr));
537 }
538 }
539 }
540 /*---------------------------------------------------------------------------*/
timediff_ms(struct timeval prior,struct timeval latter)541 double timediff_ms (struct timeval prior, struct timeval latter)
542 {
543 return
544 (latter.tv_usec - prior.tv_usec) / 1000. +
545 (latter.tv_sec - prior.tv_sec) * 1000.;
546 }
547 /*---------------------------------------------------------------------------*/
EvtPacketInfoDefaultHandler(lft_session_params * sess,const EvtPacketInfoParam * ehip)548 static void EvtPacketInfoDefaultHandler(lft_session_params * sess, const EvtPacketInfoParam * ehip)
549 {
550 char ind=' ';
551
552 if(ehip->tp->recv.tv_sec) {
553 if (ehip->last_hop.s_addr != ehip->tp->hopaddr.s_addr) {
554 if (sess->do_aslookup) {
555 if(global_output_style==1)
556 printf(" asn=\"%d\"", ehip->asnumber);
557 else
558 {
559 if (ehip->asnumber)
560 printf(" [%d]", ehip->asnumber);
561 else
562 printf(" [AS?]");
563 }
564 }
565 if (sess->do_netlookup) {
566 if(global_output_style==1)
567 printf(" net=\"%s\"", ehip->netname);
568 else
569 {
570 if(ehip->netname && strlen(ehip->netname)>0)
571 printf(" [%s]", ehip->netname);
572 else
573 printf(" [Net?]");
574 }
575 }
576 if (ehip->tp->icmp_type < -2 || ehip->tp->icmp_type > 17)
577 {
578 if(global_output_style==1)
579 printf(" icmpcode=\"%d\"", ehip->tp->icmp_type);
580 else
581 printf (" [icmp code %d]", ehip->tp->icmp_type);
582 }
583 else
584 if (ehip->tp->icmp_type >= 0)
585 {
586 if(global_output_style==1)
587 printf (" icmpmsg=\"%s\"", icmp_messages[ehip->tp->icmp_type + 1]);
588 else
589 printf (" [%s]", icmp_messages[ehip->tp->icmp_type + 1]);
590 }
591
592 if (ehip->tp->icmp_type == -1) {
593 if(global_output_style==1)
594 printf(" trgstate=\"");
595 else
596 printf(" [target");
597 if(sess->protocol==0 || sess->protocol==4)
598 {
599 if(!(global_output_style==1))
600 printf(" ");
601 if (sess->target_open > 0)
602 printf("open");
603 else
604 {
605 if(sess->target_filtered > 0)
606 printf("filtered");
607 else
608 printf("closed");
609 }
610 }
611 if(global_output_style==1)
612 printf("\"");
613 else
614 printf("]");
615 }
616 if(ehip->is_asseam)
617 {
618 if(global_output_style==1)
619 printf(" asseam=\"1");
620 else
621 printf(" (AS-Method Seam");
622 }
623 if(ehip->is_netseam)
624 {
625 if(global_output_style==1)
626 printf(" netseam=\"1");
627 else
628 {
629 if(ehip->is_asseam)
630 printf(", Network-Method Seam");
631 else
632 printf(" (Network-Method Seam");
633 }
634 }
635 if(ehip->is_asseam || ehip->is_netseam)
636 {
637 if(ehip->seam_traced)
638 {
639 if(global_output_style==1)
640 printf("\" seamstate=\"");
641 else
642 printf(": ");
643 if(ehip->is_open)
644 printf("OPEN");
645 else
646 {
647 if(ehip->is_filtered)
648 printf("FILTERED");
649 else
650 printf("CLOSED");
651 }
652 }
653 if(global_output_style==1)
654 printf("\"");
655 else
656 printf(")");
657 }
658 if(global_output_style!=1)
659 printf(" ");
660 print_host (sess, ehip->tp->hopaddr);
661 if (ehip->tp->icmp_type == -1 && (sess->protocol<2 || sess->protocol>3))
662 {
663 if(global_output_style==1)
664 printf(" port=\"%d\"",sess->dport);
665 else
666 printf(":%d",sess->dport);
667 }
668 }
669 else
670 {
671 if(global_output_style==1)
672 ind=';';
673 else
674 ind='/';
675 }
676 if(global_output_style==1)
677 {
678 if(ind==';')
679 printf (";%.1f", timediff_ms(ehip->tp->sent, ehip->tp->recv));
680 else
681 printf (" timems=\"%.1f", timediff_ms(ehip->tp->sent, ehip->tp->recv));
682 }
683 else
684 printf ("%c%.1f", ind, timediff_ms(ehip->tp->sent, ehip->tp->recv));
685 }
686 }
687 /*---------------------------------------------------------------------------*/
LFTDefaultEventHandler(lft_session_params * sess,int code,const void * params)688 static void LFTDefaultEventHandler(lft_session_params * sess, int code, const void * params)
689 {
690 const EvtSentPacketParam * spparam;
691 const EvtNoReplyParam * nrparam;
692 const struct trace_packet_s * packet;
693 const EvtDebugCheckpoint1Param * edcpparam;
694 const EvtNonSeqPacketParam * enspparam;
695 const EvtRecvPacketParam * erpparam;
696 const EvtIncomingICMPUDPParam * eiiuparam;
697 const EvtIncomingICMPTCPParam * eiitparam;
698 const EvtIncomingICMPEchoParam * eiiiparam;
699 const EvtIncomingICMPICMPParam * eicmparam;
700 const struct tcphdr *tcp;
701 const struct udphdr *udp;
702 const struct icmp_echo_header_s * echo;
703 const struct ip * ip;
704 const struct icmp * icmp;
705
706 if(global_output_style==1 && code!=EVT_RPT_PACKET_LIST_END && code!=EVT_RPT_PACKET_INFO)
707 printf("<event code=\"%d\"",code);
708 switch(code)
709 {
710 case EVT_AUTOCONFIGURED_TO_PORTS:
711 if(global_output_style<2)
712 {
713 if(global_output_style)
714 printf(" sport=\"%d\" dport=\"%d\" />\n",sess->sport,sess->dport);
715 else
716 printf ("Autoconfigured to source port %d, destination port %d.\n",sess->sport, sess->dport);
717 }
718 break;
719 case EVT_ADDRESS_INITIALIZED:
720 if(global_output_style<2)
721 {
722 print_host (sess, sess->local_address);
723 if(global_output_style==1)
724 {
725 printf(" protocol=\"%d\"",sess->protocol);
726 if(sess->protocol!=2 && sess->protocol!=3)
727 {
728 if (sess->random_source)
729 printf (" rndsport=\"1\" sport=\"%d\"", sess->sport);
730 else
731 printf (" rndsport=\"0\" sport=\"%d\"", sess->sport);
732 }
733 printf(" />\n");
734 }
735 else
736 {
737 if(!global_output_style)
738 {
739 if(sess->protocol==2 || sess->protocol==3)
740 printf("\n");
741 else
742 if (sess->random_source)
743 printf (":%d (pseudo-random)\n", sess->sport);
744 else
745 printf (":%d\n", sess->sport);
746 }
747 }
748 }
749 break;
750 case EVT_SENT_PACKET:
751 spparam=(const EvtSentPacketParam *)params;
752 if(global_output_style==1)
753 {
754 printf(" protocol=\"%d\" ttl=\"%d\"", sess->protocol, spparam->nhop+1);
755 if(!sess->protocol || sess->protocol==4)
756 {
757 int flcnt=0;
758 printf(" seq=\"%u\" xflags=\"%#x\" flags=\"", spparam->tseq, spparam->flags);
759 if (spparam->flags & TH_RST)
760 {
761 printf ("RST");
762 flcnt++;
763 }
764 if (spparam->flags & TH_ACK)
765 {
766 if(flcnt)
767 printf(";");
768 printf("ACK");
769 flcnt++;
770 }
771 if (spparam->flags & TH_SYN)
772 {
773 if(flcnt)
774 printf(";");
775 printf ("SYN");
776 flcnt++;
777 }
778 if (spparam->flags & TH_FIN)
779 {
780 if(flcnt)
781 printf(";");
782 printf ("FIN");
783 flcnt++;
784 }
785 if(!flcnt)
786 printf("none");
787 printf("\" />\n");
788 }
789 else if(sess->protocol==1)
790 {
791 printf(" dport=\"%d\" />\n", (sess->dport + spparam->tttl));
792 }
793 else
794 {
795 printf(" />\n");
796 }
797 }
798 else if(!global_output_style)
799 {
800 if(!sess->protocol || sess->protocol==4)
801 {
802 printf("SENT TCP TTL=%d SEQ=%u FLAGS=%#x ( ", spparam->nhop+1, spparam->tseq, spparam->flags);
803 if (spparam->flags & TH_RST)
804 printf ("RST ");
805 if (spparam->flags & TH_ACK)
806 printf ("ACK ");
807 if (spparam->flags & TH_SYN)
808 printf ("SYN ");
809 if (spparam->flags & TH_FIN)
810 printf ("FIN ");
811 printf(")\n");
812 }
813 else if(sess->protocol==1)
814 {
815 printf("SENT UDP TTL=%d DPORT=%d\n", spparam->nhop+1, (sess->dport + spparam->tttl));
816 }
817 else
818 {
819 printf("SENT ICMP TTL=%d\n", spparam->nhop+1);
820 }
821 }
822 break;
823 case EVT_SHOW_PAYLOAD:
824 packet=(const struct trace_packet_s *)params;
825 if(global_output_style==1)
826 {
827 if(!packet->payload_len)
828 printf(" payloadlen=\"%d\" />\n", packet->payload_len);
829 else
830 printf(" payloadlen=\"%d\">%s</event>\n", packet->payload_len, packet->payload);
831 }
832 else if(!global_output_style)
833 {
834 if(!packet->payload_len)
835 printf("Payload: Length=%d Contents=EMPTY\n", packet->payload_len);
836 else
837 printf("Payload: Length=%d Contents=\"%s\"\n", packet->payload_len, packet->payload);
838 }
839 break;
840 case EVT_SHOW_UDP_CHECKSUM:
841 packet=(const struct trace_packet_s *)params;
842 if(global_output_style==1)
843 printf(" udpsum=\"%#x\"/>\n",packet->udp_hdr.uh_sum);
844 else if(!global_output_style)
845 printf("UDP Checksum = %#x\n",packet->udp_hdr.uh_sum);
846 break;
847 case EVT_SHOW_TCP_CHECKSUM:
848 packet=(const struct trace_packet_s *)params;
849 if(global_output_style==1)
850 printf(" tcpsum=\"%#x\"/>\n",packet->tcp_hdr.th_sum);
851 else if(!global_output_style)
852 printf("TCP Checksum = %#x\n",packet->tcp_hdr.th_sum);
853 break;
854 case EVT_SHOW_HOPS:
855 if(global_output_style==1)
856 printf(" uphops=\"%d\" />\n", (int)(*((const short *)params)));
857 else if(!global_output_style)
858 printf("Upping states of the hops following %d\n", (int)(*((const short *)params)));
859 break;
860 case EVT_SHOW_NUM_HOPS:
861 if(global_output_style<2)
862 {
863 if(global_output_style)
864 printf(" numhops=\"%d\" />\n", (sess->num_hops+1));
865 else
866 printf ("Concluding with %d hops.\n", (sess->num_hops+1));
867 }
868 break;
869 case EVT_TRACE_COMPLETED:
870 if(global_output_style<2)
871 {
872 if(global_output_style)
873 {
874 printf(" />\n");
875 }
876 else
877 {
878 if (sess->num_hops && !sess->nostatus && !sess->noisy)
879 printf ("T\n");
880 else if (!sess->noisy && !sess->nostatus)
881 printf ("\n");
882 }
883 }
884 break;
885 case EVT_ON_RESOLUTION:
886 if(global_output_style<2)
887 {
888 if(global_output_style)
889 {
890 printf(" asresolutiontype=\"");
891 if(sess->use_radb)
892 printf ("RADB");
893 else
894 if(sess->use_cymru)
895 printf ("Cymru");
896 else
897 if(sess->use_ris)
898 printf ("RIPE");
899 else
900 printf ("PWhoIs");
901 printf("\" />\n");
902 }
903 else
904 {
905 if(sess->use_radb)
906 printf ("Using RADB for in-line AS resolution...\n");
907 else
908 if(sess->use_cymru)
909 printf ("Using Cymru for bulk AS resolution...\n");
910 else
911 if(sess->use_ris)
912 printf ("Using RIPE NCC RIS for bulk AS resolution...\n");
913 else
914 printf ("Using Prefix WhoIs for bulk AS resolution...\n");
915 }
916 }
917 break;
918 case EVT_TRACE_REPORT_START:
919 if(global_output_style<2)
920 {
921 if(!global_output_style)
922 printf ("TTL LFT trace to ");
923 print_host (sess, sess->remote_address);
924 if(global_output_style)
925 {
926 printf(" protocol=\"%d\"",sess->protocol);
927 switch(sess->protocol)
928 {
929 case 0:
930 printf(" protocolname=\"TCP\" dport=\"%d\" />\n",sess->dport);
931 break;
932 case 4:
933 printf(" protocolname=\"TCP\" dportrange=\"%d-%d\" />\n",sess->dport,(sess->dport + (*((const int *)params))));
934 break;
935 case 1:
936 printf(" protocolname=\"UDP\" dportrange=\"%d-%d\" />\n",sess->dport,(sess->dport + (*((const int *)params))));
937 break;
938 case 2:
939 printf(" protocolname=\"ICMP\" />\n");
940 break;
941 case 3:
942 printf(" protocolname=\"RFC1393\" />\n");
943 break;
944 }
945 }
946 else
947 {
948 switch(sess->protocol)
949 {
950 case 0:
951 printf(":%d/tcp\n",sess->dport);
952 break;
953 case 4:
954 printf(":%d-%d/tcp\n",sess->dport, (sess->dport + (*((const int *)params))));
955 break;
956 case 1:
957 printf(":%d-%d/udp\n",sess->dport, (sess->dport + (*((const int *)params))));
958 break;
959 case 2:
960 printf("/icmp\n");
961 break;
962 case 3:
963 printf("/rfc1393\n");
964 break;
965 }
966 }
967 }
968 break;
969 case EVT_RPT_NO_REPLY:
970 if(global_output_style<2)
971 {
972 nrparam=(const EvtNoReplyParam *)params;
973 if(global_output_style)
974 {
975 printf(" firstholehop=\"%d\" lastholehop=\"%d\" />\n", nrparam->hopno - nrparam->noreply + 1, nrparam->hopno);
976 }
977 else
978 {
979 if (nrparam->noreply == 1)
980 printf("** [neglected] no reply packets received from TTL %d\n", nrparam->hopno);
981 if (nrparam->noreply > 1)
982 printf("** [neglected] no reply packets received from TTLs %d through %d\n", nrparam->hopno - nrparam->noreply + 1, nrparam->hopno);
983 }
984 }
985 break;
986 case EVT_RPT_FRW_INSPECT_PACKS:
987 if(global_output_style<2)
988 {
989 if(global_output_style)
990 printf(" />\n");
991 else
992 printf("** [firewall] the next gateway may statefully inspect packets\n");
993 }
994 break;
995 case EVT_RPT_FRW_STATE_FILTER:
996 if(global_output_style<2)
997 {
998 if(global_output_style)
999 printf(" />\n");
1000 else
1001 printf("** [firewall] the next gateway may implement a flag-based state filter\n");
1002 }
1003 break;
1004 case EVT_RPT_BSD_BUG:
1005 if(global_output_style<2)
1006 {
1007 if(global_output_style)
1008 printf(" />\n");
1009 else
1010 printf("** [4.2-3 BSD bug?] the next gateway may errantly reply with reused TTLs\n");
1011 }
1012 break;
1013 case EVT_RPT_PACKET_INFO:
1014 if(global_output_style<2)
1015 {
1016 EvtPacketInfoDefaultHandler(sess, (const EvtPacketInfoParam *)params);
1017 }
1018 break;
1019 case EVT_RPT_PACKET_LIST_END:
1020 if(global_output_style<2)
1021 {
1022 if(global_output_style)
1023 printf("\" />\n");
1024 else
1025 printf ("ms\n");
1026 }
1027 break;
1028 case EVT_RPT_HOP_INFO_START:
1029 if(global_output_style<2)
1030 {
1031 if(global_output_style)
1032 printf (" index=\"%2d\"", (*((const int *)params)) + 1);
1033 else
1034 printf ("%2d ", (*((const int *)params)) + 1);
1035 }
1036 break;
1037 case EVT_RPT_NO_HOPS:
1038 if(global_output_style<2)
1039 {
1040 if(global_output_style)
1041 {
1042 printf(" protocol=\"%d\"",sess->protocol);
1043 if(sess->protocol==0 || sess->protocol==4)
1044 printf(" protocolname=\"TCP\"");
1045 else
1046 if(sess->protocol==1)
1047 printf(" protocolname=\"UDP\"");
1048 else
1049 printf(" protocolname=\"ICMP\"");
1050 if(sess->target_anomaly)
1051 printf(" targetanomaly=\"1\"");
1052 if(sess->target_anomaly || sess->protocol==0)
1053 printf(" dport=\"%d\"",sess->dport);
1054 if(!sess->target_anomaly && (sess->protocol==1 || sess->protocol==4))
1055 printf(" dportrange=\"%d-%d\"",sess->dport,(sess->dport + (*((const int *)params))));
1056 printf(" />\n");
1057 }
1058 else
1059 {
1060 if (sess->target_anomaly)
1061 printf("** [%d/tcp sequence anomaly from target] Try advanced options (use -VV to see packets).\n", sess->dport);
1062 else if (sess->protocol==1)
1063 printf("** [%d-%d/udp no reply from target] Use -VV to see packets.\n", sess->dport, (sess->dport + (*((const int *)params))));
1064 else if (sess->protocol==0)
1065 printf("** [%d/tcp no reply from target] Try advanced options (use -VV to see packets).\n", sess->dport);
1066 else if (sess->protocol==4)
1067 printf("** [%d-%d/tcp no reply from target] Use -VV to see packets.\n", sess->dport, (sess->dport + (*((const int *)params))));
1068 else
1069 printf("** [icmp no reply from target] Try advanced options (use -VV to see packets).\n");
1070 }
1071 }
1072 break;
1073 case EVT_RPT_TIME_TRACE:
1074 if(global_output_style<2)
1075 {
1076 gettimeofday (&(sess->now), NULL);
1077 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
1078 if(!sess->UseLocalTime)
1079 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *) gmtime((time_t *) &(sess->now.tv_sec)));
1080 else
1081 #endif
1082 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *)localtime((time_t *) &(sess->now.tv_sec)));
1083 if(global_output_style)
1084 {
1085 printf (" finishtime=\"%s\"", tbuf);
1086 printf (" elapsed=\"%.2f\"",(timediff_ms(sess->begin_time, sess->now) / 1000));
1087 printf (" tracingtime=\"%.2f\"",
1088 (timediff_ms(sess->begin_time, sess->trace_done_time) / 1000));
1089 if (sess->resolve_names || sess->do_aslookup || sess->do_netlookup)
1090 printf(" resolvingtime=\"%.2f\"", (timediff_ms(sess->trace_done_time, sess->now) / 1000));
1091 printf(" />\n");
1092 }
1093 else
1094 {
1095 printf ("LFT trace finished at %s", tbuf);
1096 printf (" (%.2fs elapsed)",(timediff_ms(sess->begin_time, sess->now) / 1000));
1097 if (sess->noisy) {
1098 printf ("\nTime spent tracing: %.2fs",
1099 (timediff_ms(sess->begin_time, sess->trace_done_time) / 1000));
1100 if (sess->resolve_names || sess->do_aslookup || sess->do_netlookup)
1101 printf(", resolving: %.2fs", (timediff_ms(sess->trace_done_time, sess->now) / 1000));
1102 }
1103 printf("\n");
1104 }
1105 }
1106 break;
1107 case EVT_ON_EXIT:
1108 if(global_output_style==1)
1109 printf(" />\n");
1110 sess->exit_state=-100;
1111 if(global_output_style==2)
1112 GraphVizOutput(sess);
1113 break;
1114 case EVT_TTL_NO_REPLY:
1115 if(global_output_style<2)
1116 {
1117 if(global_output_style)
1118 printf(" ttl=\"%d\" />\n", (*((const int *)params)));
1119 else
1120 printf("No reply on TTL %d\n", (*((const int *)params)));
1121 }
1122 break;
1123 case EVT_PROGRESS_NO_REPLY:
1124 if(global_output_style<2)
1125 {
1126 if(global_output_style)
1127 printf(" />\n");
1128 else
1129 printf("*");
1130 }
1131 break;
1132 case EVT_PROGRESS_SKIP_PACKET:
1133 if(global_output_style<2)
1134 {
1135 if(global_output_style)
1136 printf(" />\n");
1137 else
1138 printf("?");
1139 }
1140 break;
1141 case EVT_TTL_TOUT_RESEND:
1142 if(global_output_style<2)
1143 {
1144 if(global_output_style)
1145 printf(" ttl=\"%d\" />\n", (*((const int *)params)));
1146 else
1147 printf("TTL %d timed out, (resending)\n",(*((const int *)params)));
1148 }
1149 break;
1150 case EVT_TTL_TOUT_GIVINGUP:
1151 if(global_output_style<2)
1152 {
1153 if(global_output_style)
1154 printf(" ttl=\"%d\" />\n", (*((const int *)params)));
1155 else
1156 printf("TTL %d timed out, (giving up)\n",(*((const int *)params)));
1157 }
1158 break;
1159 case EVT_DBG_CHECKPOINT1:
1160 if(global_output_style<2)
1161 {
1162 edcpparam=(const EvtDebugCheckpoint1Param *)params;
1163 if(global_output_style)
1164 {
1165 printf (" hilength=\"%d\" last_return=\"%d\"", sess->hop_info_length, edcpparam->last_return);
1166 printf (" no_reply=\"%d\" ahead_limit=\"%d\"", edcpparam->no_reply, sess->ahead_limit);
1167 printf (" num_hops=\"%d\" need_reply=\"%d\" />\n", sess->num_hops, edcpparam->need_reply);
1168 }
1169 else
1170 {
1171 printf ("| hilength %d, last_return %d\n", sess->hop_info_length, edcpparam->last_return);
1172 printf ("| no_reply %d, ahead_limit %d\n", edcpparam->no_reply, sess->ahead_limit);
1173 printf ("| num_hops %d, need_reply %d\n", sess->num_hops, edcpparam->need_reply);
1174 }
1175 }
1176 break;
1177 case EVT_CANT_RELIABLY_RTRIP:
1178 if(global_output_style<2)
1179 {
1180 if(global_output_style)
1181 printf(" />\n");
1182 else
1183 printf("LFT can\'t reliably round-trip. Close-proximity filter in the way?\n");
1184 }
1185 break;
1186 case EVT_HAVE_UNANSWERRED_HOPS:
1187 if(global_output_style<2)
1188 {
1189 if(global_output_style)
1190 printf(" />\n");
1191 else
1192 printf("I still have unanswered hops.\n");
1193 }
1194 break;
1195 case EVT_TOO_FAR_AHEAD:
1196 if(global_output_style<2)
1197 {
1198 if(global_output_style)
1199 printf(" />\n");
1200 else
1201 printf("I\'m too far ahead, returning.\n");
1202 }
1203 break;
1204 case EVT_HAVE_GAPS:
1205 if(global_output_style<2)
1206 {
1207 if(global_output_style)
1208 printf(" />\n");
1209 else
1210 printf("I know the distance to the target, but I have gaps to fill. Returning...\n");
1211 }
1212 break;
1213 case EVT_EITHER_RESP_OR_TOUT:
1214 if(global_output_style<2)
1215 {
1216 if(global_output_style)
1217 printf(" />\n");
1218 else
1219 printf("Everyone either responded or timed out. ");
1220 }
1221 break;
1222 case EVT_LOOKFOR_UNINC_ACK:
1223 if(global_output_style<2)
1224 {
1225 if(global_output_style)
1226 printf(" />\n");
1227 else
1228 printf("\nNo match in sequence check, looking for a match inside seq-.\n");
1229 }
1230 break;
1231 case EVT_LOOKFOR_OFF_BY_LEN:
1232 if(global_output_style<2)
1233 {
1234 if(global_output_style)
1235 printf(" />\n");
1236 else
1237 printf("No match in seq-, looking for a match inside seq+len.\n");
1238 }
1239 break;
1240 case EVT_LOOKFOR_LAST_RESORT:
1241 if(global_output_style<2)
1242 {
1243 if(global_output_style)
1244 printf(" />\n");
1245 else
1246 printf("No match in seq+len, looking for a match inside last resort loop.\n");
1247 }
1248 break;
1249 case EVT_SKIP_PACKET:
1250 if(global_output_style<2)
1251 {
1252 if(global_output_style)
1253 printf(" />\n");
1254 else
1255 printf("(packet not meant for us, skip)\n");
1256 }
1257 break;
1258 case EVT_ACK_WAS_NOT_INC:
1259 if(global_output_style<2)
1260 {
1261 enspparam=(const EvtNonSeqPacketParam *)params;
1262 if(global_output_style)
1263 printf (" src=\"%s\" pttl=\"%d\" />\n", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1264 else
1265 {
1266 printf ("SRC=%s PTTL=%d\n", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1267 printf ("Target\'s ACK was not incremented. ");
1268 }
1269 }
1270 break;
1271 case EVT_RST_REL_TO_ISN:
1272 if(global_output_style<2)
1273 {
1274 enspparam=(const EvtNonSeqPacketParam *)params;
1275 if(global_output_style)
1276 {
1277 printf (" src=\"%s\" pttl=\"%d\"", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1278 printf (" payloadlen=\"%d\" />\n", sess->payloadlen);
1279 }
1280 else
1281 {
1282 printf ("SRC=%s PTTL=%d\n", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1283 printf ("Target\'s RST relates to the ISN + payload length (%d). ", sess->payloadlen);
1284 }
1285 }
1286 break;
1287 case EVT_ACK_WAS_WAY_OFF:
1288 if(global_output_style<2)
1289 {
1290 enspparam=(const EvtNonSeqPacketParam *)params;
1291 if(global_output_style)
1292 printf (" src=\"%s\" pttl=\"%d\" />\n", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1293 else
1294 {
1295 printf ("SRC=%s PTTL=%d\n", inet_ntoa (enspparam->ipaddr), enspparam->tp->hopno+1);
1296 printf ("Target\'s ACK was way off. ");
1297 }
1298 }
1299 break;
1300 case EVT_DUPLICATE_PACKET:
1301 if(global_output_style<2)
1302 {
1303 if(global_output_style)
1304 printf(" />\n");
1305 else
1306 printf ("(duplicate packet, skip)\n");
1307 }
1308 break;
1309 case EVT_PROGRESS_DUPLICATE:
1310 if(global_output_style<2)
1311 {
1312 if(global_output_style)
1313 printf(" />\n");
1314 else
1315 printf("!");
1316 }
1317 break;
1318 case EVT_RECV_PACKET:
1319 if(global_output_style<2)
1320 {
1321 erpparam=(const EvtRecvPacketParam *)params;
1322 if(global_output_style)
1323 printf (" src=\"%s\" pttl=\"%d\" pseq=\"%u\" />\n", inet_ntoa (erpparam->ipaddr), erpparam->tp->hopno+1, erpparam->seq);
1324 else
1325 printf ("SRC=%s PTTL=%d PSEQ=%u\n", inet_ntoa (erpparam->ipaddr), erpparam->tp->hopno+1, erpparam->seq);
1326 }
1327 break;
1328 case EVT_PROGRESS_OK:
1329 if(global_output_style<2)
1330 {
1331 if(global_output_style)
1332 printf(" />\n");
1333 else
1334 printf(".");
1335 }
1336 break;
1337 case EVT_TCP_PORT_CLOSED:
1338 if(global_output_style<2)
1339 {
1340 if(global_output_style)
1341 printf (" dport=\"%d\" />\n", sess->dport);
1342 else
1343 printf ("Port %d/tcp appears to be closed; target sent RST.\n", sess->dport);
1344 }
1345 break;
1346 case EVT_TCP_PORT_OPEN:
1347 if(global_output_style<2)
1348 {
1349 if(global_output_style)
1350 printf (" dport=\"%d\" />\n", sess->dport);
1351 else
1352 printf ("Port %d/tcp open; target attempted handshake.\n", sess->dport);
1353 }
1354 break;
1355 case EVT_PROCESS_PACKET_START:
1356 if(global_output_style<2)
1357 {
1358 if(global_output_style)
1359 printf(" />\n");
1360 else
1361 printf("Received new data from packet capture; processing.\n");
1362 }
1363 break;
1364 case EVT_UDP_NOT_FOR_US:
1365 if(global_output_style<2)
1366 {
1367 if(global_output_style)
1368 printf(" />\n");
1369 else
1370 {
1371 if (sess->noisy>3)
1372 printf("Not for us\n");
1373 else
1374 printf("?");
1375 }
1376 }
1377 break;
1378 case EVT_INCOMING_ICMP_ICMP:
1379 if(global_output_style<2)
1380 {
1381 eicmparam=(const EvtIncomingICMPICMPParam *)params;
1382 if(global_output_style)
1383 {
1384 printf(" src=\"%s\" proto=\"%d\" ttl=\"%d\"", inet_ntoa(eicmparam->ip->ip_src), eicmparam->ip->ip_p, eicmparam->ip->ip_ttl);
1385 printf(" protocolname=\"ICMP\"");
1386 if (eicmparam->icmp->icmp_type == ICMP_TIMXCEED)
1387 printf(" icmptype=\"ICMP_TIMXCEED\"");
1388 else if (eicmparam->icmp->icmp_type == ICMP_UNREACH)
1389 printf(" icmptype=\"ICMP_UNREACH\"");
1390 printf(" echoid=\"%d\" echoseq=\"%d\"",(int)eicmparam->echo->id, (int)eicmparam->echo->sequence);
1391 printf(" />\n");
1392 }
1393 else
1394 {
1395 printf("INCOMING IP: SRC=%s PROTO=%d TTL=%d\n", inet_ntoa(eicmparam->ip->ip_src), eicmparam->ip->ip_p, eicmparam->ip->ip_ttl);
1396 printf("\\->ICMP+ICMP: ");
1397 if (eicmparam->icmp->icmp_type == ICMP_TIMXCEED)
1398 printf("TTL exceeded; ");
1399 else if (eicmparam->icmp->icmp_type == ICMP_UNREACH)
1400 printf("unreachable; ");
1401 printf("ICMP echo ID=%d SEQ=%d\n",(int)eicmparam->echo->id, (int)eicmparam->echo->sequence);
1402 }
1403 }
1404 break;
1405 case EVT_INCOMING_ICMP_Echo:
1406 if(global_output_style<2)
1407 {
1408 eiiiparam=(const EvtIncomingICMPEchoParam *)params;
1409 if(global_output_style)
1410 {
1411 printf(" src=\"%s\" proto=\"%d\" ttl=\"%d\"", inet_ntoa(eiiiparam->ip->ip_src), eiiiparam->ip->ip_p, eiiiparam->ip->ip_ttl);
1412 printf(" protocolname=\"ECHO\" echoid=\"%d\" echoseq=\"%d\"",(int)eiiiparam->echo->id, (int)eiiiparam->echo->sequence);
1413 printf(" />\n");
1414 }
1415 else
1416 {
1417 printf("INCOMING IP: SRC=%s PROTO=%d TTL=%d\n", inet_ntoa(eiiiparam->ip->ip_src), eiiiparam->ip->ip_p, eiiiparam->ip->ip_ttl);
1418 printf("\\->ICMP+ICMP echo: ");
1419 printf("ICMP echo ID=%d SEQ=%d\n",(int)eiiiparam->echo->id, (int)eiiiparam->echo->sequence);
1420 }
1421 }
1422 break;
1423 case EVT_INCOMING_ICMP_UDP:
1424 if(global_output_style<2)
1425 {
1426 eiiuparam=(const EvtIncomingICMPUDPParam *)params;
1427 if(global_output_style)
1428 {
1429 printf(" src=\"%s\" proto=\"%d\" ttl=\"%d\"", inet_ntoa (eiiuparam->orig_ip->ip_src), eiiuparam->ip->ip_p, eiiuparam->ip->ip_ttl);
1430 if (eiiuparam->icmp->icmp_type == ICMP_TIMXCEED)
1431 printf(" icmptype=\"ICMP_TIMXCEED\"");
1432 else if (eiiuparam->icmp->icmp_type == ICMP_UNREACH)
1433 printf(" icmptype=\"ICMP_UNREACH\"");
1434 printf(" protocolname=\"UDP\" sport=\"%d\" dport=\"%d\"",(ntohs (eiiuparam->udp->uh_sport)), (ntohs (eiiuparam->udp->uh_dport)));
1435 printf(" />\n");
1436 }
1437 else
1438 {
1439 printf("INCOMING IP: SRC=%s PROTO=%d TTL=%d\n", inet_ntoa (eiiuparam->orig_ip->ip_src), eiiuparam->ip->ip_p, eiiuparam->ip->ip_ttl);
1440 printf("\\->ICMP+UDP: ");
1441 if (eiiuparam->icmp->icmp_type == ICMP_TIMXCEED)
1442 printf("TTL exceeded; ");
1443 else if (eiiuparam->icmp->icmp_type == ICMP_UNREACH)
1444 printf("unreachable; ");
1445 printf("UDP SPORT=%d DPORT=%d\n", (ntohs (eiiuparam->udp->uh_sport)), (ntohs (eiiuparam->udp->uh_dport)));
1446 }
1447 }
1448 break;
1449 case EVT_INCOMING_ICMP_TCP:
1450 if(global_output_style<2)
1451 {
1452 eiitparam=(const EvtIncomingICMPTCPParam *)params;
1453 if(global_output_style)
1454 {
1455 printf(" src=\"%s\" proto=\"%d\" ttl=\"%d\"", inet_ntoa (eiitparam->orig_ip->ip_src), eiitparam->ip->ip_p, eiitparam->ip->ip_ttl);
1456 if (eiitparam->icmp->icmp_type == ICMP_TIMXCEED)
1457 printf(" icmptype=\"ICMP_TIMXCEED\"");
1458 else if (eiitparam->icmp->icmp_type == ICMP_UNREACH)
1459 printf(" icmptype=\"ICMP_UNREACH\"");
1460 printf(" protocolname=\"TCP\" sport=\"%d\" dport=\"%d\"",(ntohs (eiitparam->tcp->th_sport)), (ntohs (eiitparam->tcp->th_dport)));
1461 printf(" />\n");
1462 }
1463 else
1464 {
1465 printf("INCOMING IP: SRC=%s PROTO=%d TTL=%d\n", inet_ntoa (eiitparam->orig_ip->ip_src), eiitparam->ip->ip_p, eiitparam->ip->ip_ttl);
1466 printf("\\->ICMP+TCP: ");
1467 if (eiitparam->icmp->icmp_type == ICMP_TIMXCEED)
1468 printf("TTL exceeded; ");
1469 else if (eiitparam->icmp->icmp_type == ICMP_UNREACH)
1470 printf("unreachable; ");
1471 printf("TCP SPORT=%d DPORT=%d\n", (ntohs (eiitparam->tcp->th_sport)), (ntohs (eiitparam->tcp->th_dport)));
1472 }
1473 }
1474 break;
1475 case EVT_RCVD_ICMP_Echo:
1476 if(global_output_style<2)
1477 {
1478 echo=(const struct icmp_echo_header_s *)params;
1479 if(global_output_style)
1480 printf(" id=\"%d\" seq=\"%d\" />\n",(int)echo->id, (int)echo->sequence);
1481 else
1482 printf("RCVD ICMP echo ID=%d SEQ=%d ",(int)echo->id, (int)echo->sequence);
1483 }
1484 break;
1485 case EVT_RCVD_ICMP_ICMP:
1486 if(global_output_style<2)
1487 {
1488 icmp=(const struct icmp *)params;
1489 if(global_output_style)
1490 printf(" icmptype=\"%d\" icmpcode=\"%d\" />\n",(int)icmp->icmp_type,(int)icmp->icmp_code);
1491 else
1492 printf("RCVD ICMP type=%d code=%d ",(int)icmp->icmp_type,(int)icmp->icmp_code);
1493 }
1494 break;
1495 case EVT_RCVD_ICMP_UDP:
1496 if(global_output_style<2)
1497 {
1498 udp=(const struct udphdr *)params;
1499 if(global_output_style)
1500 printf(" seq=\"%u\" />\n",((ntohs (udp->uh_dport)) - sess->dport));
1501 else
1502 printf ("RCVD ICMP SEQ=%u ", ((ntohs (udp->uh_dport)) - sess->dport));
1503 }
1504 break;
1505 case EVT_RCVD_ICMP_TCP:
1506 if(global_output_style<2)
1507 {
1508 tcp=(const struct tcphdr *)params;
1509 if(global_output_style)
1510 printf(" seq=\"%u\" />\n",ntohl (tcp->th_seq));
1511 else
1512 printf ("RCVD ICMP SEQ=%u ", ntohl (tcp->th_seq));
1513 }
1514 break;
1515 case EVT_RCVD_TCP:
1516 if(global_output_style<2)
1517 {
1518 tcp=(const struct tcphdr *)params;
1519 if(global_output_style)
1520 {
1521 int flcnt=0;
1522 printf(" xflags=\"%#x\" flags=\"", tcp->th_flags);
1523 if (tcp->th_flags & TH_RST)
1524 {
1525 printf ("RST");
1526 flcnt++;
1527 }
1528 if (tcp->th_flags & TH_ACK)
1529 {
1530 if(flcnt)
1531 printf(";");
1532 printf("ACK");
1533 flcnt++;
1534 }
1535 if (tcp->th_flags & TH_SYN)
1536 {
1537 if(flcnt)
1538 printf(";");
1539 printf ("SYN");
1540 flcnt++;
1541 }
1542 if (tcp->th_flags & TH_FIN)
1543 {
1544 if(flcnt)
1545 printf(";");
1546 printf ("FIN");
1547 flcnt++;
1548 }
1549 if(!flcnt)
1550 printf("none\"");
1551 else
1552 printf("\"");
1553 printf (" seq=\"%u\" ack=\"%u\"", ntohl (tcp->th_seq), ntohl (tcp->th_ack));
1554 printf(" />\n");
1555 }
1556 else
1557 {
1558 printf("RCVD TCP FLAGS=%#x ( ",tcp->th_flags);
1559
1560 if (tcp->th_flags & TH_SYN)
1561 printf ("SYN ");
1562 if (tcp->th_flags & TH_ACK)
1563 printf ("ACK ");
1564 if (tcp->th_flags & TH_FIN)
1565 printf ("FIN ");
1566 if (tcp->th_flags & TH_RST)
1567 printf ("RST ");
1568
1569 printf (") SEQ=%u ACK=%u ", ntohl (tcp->th_seq), ntohl (tcp->th_ack));
1570 }
1571 }
1572 break;
1573 case EVT_RCVD_UNKNOWN:
1574 if(global_output_style<2)
1575 {
1576 ip=(const struct ip *)params;
1577 if(global_output_style)
1578 {
1579 printf(" protocolcode=\"%d\"", ip->ip_p);
1580 #if defined(WIN32) || defined(_WIN32)
1581 printf(" ipfrom=\"%d.%d.%d.%d\" ipto=\"%d.%d.%d.%d\"",
1582 (int)ip->ip_src.s_net,(int)ip->ip_src.s_host,(int)ip->ip_src.s_lh,(int)ip->ip_src.s_impno,
1583 (int)ip->ip_dst.s_net,(int)ip->ip_dst.s_host,(int)ip->ip_dst.s_lh,(int)ip->ip_dst.s_impno);
1584 #endif
1585 printf(" />\n");
1586 }
1587 else
1588 {
1589 printf("Incoming datagram contains unsupported protocol %d.\n", ip->ip_p);
1590 #if defined(WIN32) || defined(_WIN32)
1591 if (sess->noisy > 4)
1592 printf("\t(from %d.%d.%d.%d to %d.%d.%d.%d)\n",
1593 (int)ip->ip_src.s_net,(int)ip->ip_src.s_host,(int)ip->ip_src.s_lh,(int)ip->ip_src.s_impno,
1594 (int)ip->ip_dst.s_net,(int)ip->ip_dst.s_host,(int)ip->ip_dst.s_lh,(int)ip->ip_dst.s_impno);
1595 #endif
1596 }
1597 }
1598 break;
1599 case EVT_DEVICE_SELECTED:
1600 if(global_output_style<2)
1601 {
1602 if(global_output_style)
1603 printf (" device=\"%s\" linktype=\"%d\" linktypename=\"%s\" />\n", sess->pcap_dev, sess->pcap_datalink, pcap_datalink_val_to_name(sess->pcap_datalink));
1604 else
1605 printf ("Receiving on %s, type %d (%s), transmitting on %s as ", sess->pcap_dev, sess->pcap_datalink, pcap_datalink_val_to_name(sess->pcap_datalink), sess->pcap_send_dev);
1606 }
1607 break;
1608 case EVT_SHOW_INITIAL_SEQNUM:
1609 if(global_output_style<2)
1610 {
1611 if(global_output_style)
1612 printf (" seqstart=\"%d\" />\n", sess->seq_start);
1613 else
1614 {
1615 printf ("Receive link type is %s (%d), skipping %0d bytes\n", pcap_datalink_val_to_name(sess->pcap_datalink),sess->pcap_datalink,sess->skip_header_len);
1616 printf ("Transmit Initial Sequence Number (ISN) will be %d\n", sess->seq_start);
1617 }
1618 }
1619 break;
1620 case EVT_TRACE_START:
1621 if(global_output_style<2)
1622 {
1623 if(global_output_style)
1624 {
1625 memset(&tbuf, 0, sizeof(tbuf));
1626 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
1627 if(!sess->UseLocalTime)
1628 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *) gmtime((time_t *) &(sess->begin_time.tv_sec)));
1629 else
1630 #endif
1631 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *) localtime((time_t *) &(sess->begin_time.tv_sec)));
1632 printf (" begtime=\"%s\" />\n", tbuf);
1633 }
1634 else
1635 {
1636 if (sess->timetrace) {
1637 memset(&tbuf, 0, sizeof(tbuf));
1638 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
1639 if(!sess->UseLocalTime)
1640 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *) gmtime((time_t *) &(sess->begin_time.tv_sec)));
1641 else
1642 #endif
1643 (void)strftime(tbuf, sizeof(tbuf), time_format, (struct tm *) localtime((time_t *) &(sess->begin_time.tv_sec)));
1644 printf ("LFT trace started at %s\n", tbuf);
1645 }
1646 if (!sess->nostatus && !sess->noisy)
1647 printf("Tracing ");
1648 }
1649 }
1650 break;
1651 case EVT_DBG_CHECKPOINT2:
1652 if(global_output_style<2)
1653 {
1654 if(global_output_style)
1655 printf(" />\n");
1656 else
1657 printf("Left dispatch.\n");
1658 }
1659 break;
1660 case EVT_DBG_LOG_MESSAGE:
1661 if(global_output_style<2)
1662 {
1663 if(global_output_style)
1664 printf(">%s</event>\n",(const char *)params);
1665 else
1666 printf("%s",(const char *)params);
1667 }
1668 break;
1669 case EVT_OCHECK_START:
1670 if(global_output_style<2)
1671 {
1672 if(global_output_style)
1673 {
1674 print_host (sess, sess->remote_address);
1675 printf(" dport=\"%d\" />\n",sess->dport);
1676 }
1677 else
1678 if(sess->noisy)
1679 {
1680 printf("TCP open checking started for ");
1681 print_host (sess, sess->remote_address);
1682 printf(" port %d.\n",sess->dport);
1683 }
1684 }
1685 break;
1686 case EVT_OCHECK_OPEN:
1687 if(global_output_style<2)
1688 {
1689 if(global_output_style)
1690 {
1691 print_host (sess, sess->remote_address);
1692 printf(" dport=\"%d\" />\n",sess->dport);
1693 }
1694 else
1695 if(sess->noisy)
1696 {
1697 printf("TCP port %d is open on ",sess->dport);
1698 print_host (sess, sess->remote_address);
1699 printf(".\n");
1700 }
1701 }
1702 break;
1703 }
1704 }
1705 /*---------------------------------------------------------------------------*/
1706 static LFT_CALLBACK LFTErrHandler=LFTDefaultErrorHandler;
1707 static LFT_CALLBACK LFTEvtHandler=LFTDefaultEventHandler;
1708 /*---------------------------------------------------------------------------*/
LFTInitializeCallbacks(LFT_CALLBACK error_handler,LFT_CALLBACK event_handler)1709 void LFTInitializeCallbacks(LFT_CALLBACK error_handler, LFT_CALLBACK event_handler)
1710 {
1711 if(error_handler)
1712 LFTErrHandler=error_handler;
1713 else
1714 LFTErrHandler=LFTDefaultErrorHandler;
1715 if(event_handler)
1716 LFTEvtHandler=event_handler;
1717 else
1718 LFTEvtHandler=LFTDefaultEventHandler;
1719 }
1720 /*---------------------------------------------------------------------------*/
LFTSessionOpen(void)1721 lft_session_params * LFTSessionOpen(void)
1722 {
1723 lft_session_params * sess= (lft_session_params *)malloc(sizeof(lft_session_params));
1724 memset(sess, 0,sizeof(lft_session_params));
1725 sess->scatter_ms = 20;
1726 sess->ttl_min = 0;
1727 sess->hop_info_length = 0;
1728 sess->hop_info=NULL;
1729 sess->tcp_flags = TH_SYN;
1730 sess->use_fins = 0;
1731 sess->seq_start = 0; /* generate ISN internally by default */
1732 sess->dport = 80; /* set default destination to tcp/80 HTTP */
1733 sess->sport = 53; /* set default source to tcp/53 dns-xfer */
1734 sess->auto_ports = 1; /* enable port autoselection by default */
1735 sess->random_source = 0; /* disable random source port by default */
1736 sess->set_tos = 0; /* disable set ToS bit by default */
1737 sess->userlen = 0; /* user-requested packet length */
1738 sess->payloadlen = 0; /* the final probe payloadlength */
1739 sess->payload = NULL;
1740 sess->win_len = 32768;
1741
1742 sess->timeout_ms = 250; /* timeout between retries */
1743 sess->retry_max = 2; /* number of retries before giving up */
1744 sess->retry_min = 1; /* minimum number of checks per hop */
1745 sess->ahead_limit = 5; /* number of probes we can send
1746 * without replies if we don't know
1747 * the number of hops */
1748 sess->dflag = 0;
1749
1750 sess->ttl_limit = 30; /* max # hops to traverse (highest TTL) */
1751 sess->break_on_icmp = 1; /* break on icmp other than time exceeded */
1752 sess->noisy = 0; /* disable verbose debug by default */
1753 sess->nostatus = 0; /* print status bar by default */
1754 sess->userdevsel = 0; /* by default, we'll select the device */
1755 sess->senddevsel = 0; /* by default, we won't use a spoof device */
1756 sess->resolve_names = 1; /* dns resolution enabled by default */
1757 sess->hostnames_only = 0; /* disable printing of IP addresses */
1758 sess->timetrace = 0; /* disable tracer timing by default */
1759 sess->adaptive = 0; /* disable state engine by default */
1760 sess->protocol = 0; /* use UDP instead of TCP */
1761 sess->do_netlookup = 0; /* disable netname lookup by default */
1762 sess->do_aslookup = 0; /* disable asn lookup by default */
1763 sess->use_radb = 0; /* use RADB instead of pwhois */
1764 sess->use_cymru = 0; /* use Cymru instead of pwhois */
1765 sess->use_ris = 0; /* use RIPE NCC RIS instead of pwhois */
1766
1767 sess->num_hops = 0;
1768 /*sess->num_sent = 0;*/
1769 sess->num_rcvd = 0;
1770 sess->target_open = 0;
1771 sess->target_filtered = 0;
1772 sess->target_anomaly = 0;
1773
1774 sess->hostname = NULL;
1775 sess->hostname_lsrr_size = 0;
1776 SLIST_INIT(&(sess->trace_packets));
1777 sess->trace_packets_num = 0;
1778 sess->pcap_dev = NULL;
1779 sess->pcap_datalink = -1;
1780 sess->pcap_send_dev = NULL;
1781 sess->userdev = NULL;
1782 sess->senddev = NULL;
1783
1784 sess->send_sock = 0;
1785
1786 sess->btcpmap = NULL;
1787 sess->btcpmapsize = 0;
1788 sess->btcpdpucnt = 0;
1789 sess->trg_probe_is_sent = 0;
1790
1791 sess->icmp_packet.packet = NULL;
1792
1793 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
1794 sess->recv_sock = 0;
1795 sess->wsastarted = 0;
1796 #else
1797 sess->pcapdescr = 0;
1798 #endif
1799 sess->UseLocalTime=1;
1800 sess->exit_state=0;
1801
1802 sess->is_graphviz_subquery=0;
1803 sess->check_seam=0;
1804 sess->graphviz_icon_path=NULL;
1805
1806 /*sess->wsess=w_init();*/
1807 return sess;
1808 }
1809 /*---------------------------------------------------------------------------*/
LFTSessionClose(lft_session_params * sess)1810 void LFTSessionClose(lft_session_params * sess)
1811 {
1812 struct trace_packet_info_s *tp;
1813 if(sess->hop_info)
1814 free(sess->hop_info);
1815 if(sess->send_sock > 0)
1816 #if defined(WIN32) || defined(_WIN32)
1817 closesocket(sess->send_sock);
1818 #else
1819 close(sess->send_sock);
1820 #endif
1821 #if defined(WIN32) || defined(_WIN32)
1822 if(sess->pcap_dev != NULL)
1823 free(sess->pcap_dev);
1824 if(sess->recv_sock > 0)
1825 closesocket(sess->send_sock);
1826 #else
1827 if(sess->pcapdescr != 0)
1828 {
1829 pcap_close(sess->pcapdescr);
1830 sess->pcapdescr=0;
1831 }
1832 #endif
1833 while(SLIST_FIRST(&(sess->trace_packets)))
1834 {
1835 tp=SLIST_FIRST(&(sess->trace_packets));
1836 SLIST_REMOVE_HEAD(&(sess->trace_packets), next);
1837 free(tp);
1838 }
1839 if(sess->payload)
1840 free(sess->payload);
1841 if(sess->icmp_packet.packet)
1842 free(sess->icmp_packet.packet);
1843 if(sess->btcpmap)
1844 free(sess->btcpmap);
1845 free(sess);
1846 }
1847 /*---------------------------------------------------------------------------*/
1848 /*Use TCP FIN packets exclusively (defaults are SYN)*/
LFTSetupFIN(lft_session_params * sess)1849 int LFTSetupFIN(lft_session_params * sess)
1850 {
1851 if (sess->adaptive) {
1852 LFTErrHandler(sess, WRN_CANT_SETUP_FIN, NULL);
1853 return 0;
1854 }
1855 sess->tcp_flags = TH_FIN;
1856 sess->use_fins = 1;
1857 sess->dport = 25000;
1858 sess->auto_ports = 0;
1859 return 1;
1860 }
1861 /*---------------------------------------------------------------------------*/
1862 /*Display hosts symbolically; suppress IP address display*/
LFTSetupDispSymbHost(lft_session_params * sess)1863 int LFTSetupDispSymbHost(lft_session_params * sess)
1864 {
1865 if(!sess->resolve_names) {
1866 LFTErrHandler(sess, WRN_CANT_DISP_HOST_NAMES, NULL);
1867 return 0;
1868 }
1869 sess->hostnames_only = 1;
1870 return 1;
1871 }
1872 /*---------------------------------------------------------------------------*/
LFTSetupUDPMode(lft_session_params * sess)1873 int LFTSetupUDPMode(lft_session_params * sess)
1874 {
1875 int prev_protocol;
1876 char tmp[30];
1877 prev_protocol = sess->protocol;
1878 sess->protocol = 1;
1879 if(sess->adaptive) {
1880 LFTErrHandler(sess, WRN_ADAPTIVE_DISABLED_BY_UDP, NULL);
1881 sess->adaptive = 0;
1882 }
1883 if(sess->use_fins) {
1884 LFTErrHandler(sess, WRN_FIN_DISABLED_BY_UDP, NULL);
1885 sess->use_fins = 0;
1886 }
1887 if(!sess->dflag)
1888 sess->dport = (start_dport - 1);
1889 else
1890 {
1891 if(!prev_protocol)
1892 {
1893 sprintf(tmp,"%d",sess->dport);
1894 LFTSetupDestinationPort(sess, tmp);
1895 }
1896 }
1897 sess->auto_ports = 0;
1898 return 1;
1899 }
1900 /*---------------------------------------------------------------------------*/
LFTSetupRISLookup(lft_session_params * sess)1901 int LFTSetupRISLookup(lft_session_params * sess)
1902 {
1903 int asnlkptp=ASN_LOOKUP_RIS;
1904 if(sess->use_cymru || sess->use_radb){
1905 LFTErrHandler(sess, WRN_ONLY_ONE_ASN_LOOKUP, &asnlkptp);
1906 return 0;
1907 }
1908 sess->use_radb = 0;
1909 sess->use_ris = 1;
1910 sess->use_cymru = 0;
1911 sess->do_aslookup = 1;
1912 return 1;
1913 }
1914 /*---------------------------------------------------------------------------*/
LFTSetupRADBLookup(lft_session_params * sess)1915 int LFTSetupRADBLookup(lft_session_params * sess)
1916 {
1917 int asnlkptp=ASN_LOOKUP_RADB;
1918 if(sess->use_cymru || sess->use_ris){
1919 LFTErrHandler(sess, WRN_ONLY_ONE_ASN_LOOKUP, &asnlkptp);
1920 return 0;
1921 }
1922 sess->use_radb = 1;
1923 sess->use_ris = 0;
1924 sess->use_cymru = 0;
1925 sess->do_aslookup = 1;
1926 return 1;
1927 }
1928 /*---------------------------------------------------------------------------*/
LFTSetupCYMRULookup(lft_session_params * sess)1929 int LFTSetupCYMRULookup(lft_session_params * sess)
1930 {
1931 int asnlkptp=ASN_LOOKUP_CYMRU;
1932 if(sess->use_radb || sess->use_ris){
1933 LFTErrHandler(sess, WRN_ONLY_ONE_ASN_LOOKUP, &asnlkptp);
1934 return 0;
1935 }
1936 sess->use_radb = 0;
1937 sess->use_ris = 0;
1938 sess->use_cymru = 1;
1939 sess->do_aslookup = 1;
1940 return 1;
1941 }
1942 /*---------------------------------------------------------------------------*/
lft_resolve_port(lft_session_params * sess,const char * strport)1943 int lft_resolve_port(lft_session_params * sess, const char *strport)
1944 {
1945 struct addrinfo hint, *ai;
1946 struct sockaddr_in addr;
1947 char *end;
1948 unsigned long port;
1949
1950 /*
1951 * Check if this is numeric, if so simply convert.
1952 */
1953 port = strtoul(strport, &end, 10);
1954 if (*end == '\0') {
1955 if (port > 65535) {
1956 /* XXX Error. Nothing checks for error, though. */
1957 return (-1);
1958 }
1959 return (port);
1960 }
1961
1962 /*
1963 * This is a named service, look it up.
1964 */
1965 memset(&hint, 0, sizeof hint);
1966
1967 hint.ai_family = AF_INET;
1968
1969 if (sess->protocol == 1) {
1970 hint.ai_socktype = SOCK_DGRAM;
1971 hint.ai_protocol = IPPROTO_UDP; /* UDP */
1972 } else {
1973 hint.ai_socktype = SOCK_STREAM;
1974 hint.ai_protocol = IPPROTO_TCP; /* TCP */
1975 }
1976
1977 if (getaddrinfo(NULL, strport, &hint, &ai) != 0) {
1978 /* XXX Error. Nothing checks for error, though. */
1979 return (-1);
1980 }
1981
1982 if (ai->ai_addrlen != sizeof addr) {
1983 /* XXX Error. Nothing checks for error, though. */
1984 return (-1);
1985 }
1986
1987 memcpy(&addr, ai->ai_addr, ai->ai_addrlen);
1988
1989 return (ntohs(addr.sin_port));
1990 }
1991 /*---------------------------------------------------------------------------*/
LFTSetupDestinationPort(lft_session_params * sess,char * userport)1992 int LFTSetupDestinationPort(lft_session_params * sess, char * userport)
1993 {
1994 /*
1995 char strport[50];
1996 sprintf(strport,"%u",userport);
1997 */
1998 sess->dflag++;
1999 if(sess->protocol==1)
2000 {
2001 if(lft_resolve_port(sess, userport) > (65535 - sess->ttl_limit))
2002 {
2003 sess->dport = (65535 - sess->ttl_limit) - 1;
2004 LFTErrHandler(sess, WRN_UDP_PORT_TOO_HIGH, &userport);
2005 }
2006 else
2007 sess->dport = lft_resolve_port(sess, userport) - 1;
2008 }
2009 else
2010 {
2011 sess->dport = lft_resolve_port (sess, userport);
2012 }
2013 sess->auto_ports = 0;
2014 return 1;
2015 }
2016 /*---------------------------------------------------------------------------*/
LFTSetupLengthOfPacket(lft_session_params * sess,int plen)2017 int LFTSetupLengthOfPacket(lft_session_params * sess, int plen)
2018 {
2019 if(plen > maxpacklen) {
2020 LFTErrHandler(sess, WRN_PACKET_LENGTH_TOO_HIGH, &plen);
2021 sess->userlen = maxpacklen;
2022 } else if(plen < minpacklen) {
2023 LFTErrHandler(sess, WRN_PACKET_LENGTH_TOO_LOW, &plen);
2024 sess->userlen = 0;
2025 } else
2026 sess->userlen = plen;
2027 return 1;
2028 }
2029 /*---------------------------------------------------------------------------*/
LFTSetupDisableResolver(lft_session_params * sess)2030 int LFTSetupDisableResolver(lft_session_params * sess)
2031 {
2032 if(!sess->hostnames_only) {
2033 sess->resolve_names = 0;
2034 } else {
2035 LFTErrHandler(sess, WRN_CANT_DISABLE_RESOLVER, NULL);
2036 }
2037 return 1;
2038 }
2039 /*---------------------------------------------------------------------------*/
LFTSetupSourcePort(lft_session_params * sess,int port)2040 int LFTSetupSourcePort(lft_session_params * sess, int port)
2041 {
2042 if(sess->random_source) {
2043 LFTErrHandler(sess, WRN_ALREADY_RANDOM_SPORT, NULL);
2044
2045 return 0;
2046 }
2047 sess->sport = port;
2048 return 1;
2049 }
2050 /*---------------------------------------------------------------------------*/
LFTSetupAdaptiveMode(lft_session_params * sess)2051 int LFTSetupAdaptiveMode(lft_session_params * sess)
2052 {
2053 if (sess->protocol==1) {
2054 LFTErrHandler(sess, WRN_ADAPTIVE_DISABLED_BY_UDP, NULL);
2055 return 0;
2056 }
2057 if (sess->use_fins) {
2058 LFTErrHandler(sess, WRN_ADAPTIVE_DISABLED_BY_FIN, NULL);
2059 return 0;
2060 }
2061 sess->adaptive = 1;
2062 return 1;
2063 }
2064 /*---------------------------------------------------------------------------*/
LFTSetupDevice(lft_session_params * sess,char * udev)2065 int LFTSetupDevice(lft_session_params * sess,char * udev)
2066 {
2067 if (strlen (udev) > max_net_dev_input) {
2068 LFTErrHandler(sess, ERR_DEVNAME_TOO_LONG, NULL);
2069 return 0;
2070 }
2071 sess->userdevsel = 1;
2072 sess->userdev = udev;
2073 return 1;
2074 }
2075 /*---------------------------------------------------------------------------*/
LFTSetupSendDevice(lft_session_params * sess,char * sdev)2076 int LFTSetupSendDevice(lft_session_params * sess,char * sdev)
2077 {
2078 if (strlen (sdev) > max_net_dev_input) {
2079 LFTErrHandler(sess, ERR_DEVNAME_TOO_LONG, NULL);
2080 return 0;
2081 }
2082 sess->senddevsel = 1;
2083 sess->senddev = sdev;
2084 return 1;
2085 }
2086 /*---------------------------------------------------------------------------*/
LFTSetupUTCTimes(lft_session_params * sess)2087 int LFTSetupUTCTimes(lft_session_params * sess)
2088 {
2089 #if defined(sun)
2090 if (putenv("TZ=GMT0") == -1) {
2091 LFTErrHandler(sess, WRN_UNABLE_SETUP_UTC, NULL);
2092 }
2093 #else
2094 #if !defined(WIN32) && !defined(_WIN32)
2095 if (setenv("TZ", "GMT0", 1) == -1) {
2096 LFTErrHandler(sess, WRN_UNABLE_SETUP_UTC, NULL);
2097 }
2098 #endif
2099 #endif
2100 sess->UseLocalTime=0;
2101 sess->timetrace = 1;
2102 return 1;
2103 }
2104 /*---------------------------------------------------------------------------*/
2105 /* Refactored part of code */
2106 /*---------------------------------------------------------------------------*/
new_seq(lft_session_params * sess)2107 unsigned int new_seq(lft_session_params * sess)
2108 {
2109 if (sess->adaptive) {
2110 return rand();
2111 } else {
2112 return sess->seq_start + sess->trace_packets_num;
2113 }
2114 }
2115 /*---------------------------------------------------------------------------*/
2116 #ifndef SCREWED_IP_LEN
2117 u_int32_t
ip_cksum(const struct ip * ip)2118 ip_cksum (const struct ip *ip)
2119 {
2120 register const u_short *sp = (u_short *) ip;
2121 register u_int32_t sum = 0;
2122 register int count;
2123
2124 /*
2125 * No need for endian conversions.
2126 */
2127 for (count = ip->ip_hl * 2; --count >= 0;)
2128 sum += *sp++;
2129 while (sum > 0xffff)
2130 sum = (sum & 0xffff) + (sum >> 16);
2131 sum = ~sum & 0xffff;
2132
2133 return (sum);
2134 }
2135 #endif
2136 /*---------------------------------------------------------------------------*/
2137 /* A standardized way of calculating checksums */
2138 static unsigned short
udp_cksum(unsigned short * addr,signed int len)2139 udp_cksum (unsigned short *addr, signed int len) {
2140
2141 unsigned short answer = 0;
2142 register unsigned short *w = addr;
2143 register int nleft = len;
2144 register int sum = 0;
2145
2146 while(nleft > 1) {
2147 sum += *w++;
2148 nleft -= 2;
2149 }
2150
2151 if(nleft == 1) {
2152 *(unsigned char *)(&answer) = *(unsigned char *)w;
2153 sum += answer;
2154 }
2155
2156 sum = (sum>>16) + (sum&0xffff);
2157 sum += (sum>>16);
2158 answer = ~sum;
2159 return (answer);
2160 }
2161 /*---------------------------------------------------------------------------*/
tcp_cksum(struct ip * ip,struct tcphdr * tcp,const char * payload,int payload_len)2162 u_int32_t tcp_cksum (struct ip *ip, struct tcphdr *tcp, const char * payload, int payload_len)
2163 {
2164 u_int32_t sum = 0;
2165 register int count;
2166 u_short *sp;
2167 u_short *temptcp = (u_short *)malloc(sizeof(struct tcphdr)+payload_len+4);
2168 u_int32_t tempip;
2169
2170 memset(temptcp, 0,sizeof(struct tcphdr)+payload_len+4);
2171 memcpy(temptcp, (char *)tcp, sizeof(struct tcphdr));
2172 memcpy((u_char *)temptcp+sizeof(struct tcphdr),payload,payload_len);
2173 sp = temptcp;
2174 for(count = (sizeof(struct tcphdr)+payload_len+(sizeof(struct tcphdr)+payload_len)%2)/2; --count >= 0;)
2175 sum += *sp++;
2176 free(temptcp);
2177
2178 memcpy(&tempip, &ip->ip_src, sizeof ip->ip_src);
2179 sum += (tempip >> 16) + (tempip & 0xffff);
2180
2181 memcpy(&tempip, &ip->ip_dst, sizeof ip->ip_dst);
2182 sum += (tempip >> 16) + (tempip & 0xffff);
2183
2184 sum += ip->ip_p << 8;
2185
2186 sum += htons (sizeof (struct tcphdr)+payload_len);
2187
2188 while (sum > 0xffff)
2189 sum = (sum & 0xffff) + (sum >> 16);
2190 sum = ~sum & 0xffff;
2191
2192 return (sum);
2193 }
2194 /*---------------------------------------------------------------------------*/
2195 static char *
strtolower(char * input)2196 strtolower (char *input) {
2197 char *iter = input;
2198
2199 if (input == NULL)
2200 return NULL;
2201
2202 while (*iter) {
2203 *iter = tolower (*iter);
2204 iter++;
2205 }
2206 return input;
2207 }
2208 /*---------------------------------------------------------------------------*/
2209 static void
do_auto_ports(lft_session_params * sess,char * hostname,int init_dport)2210 do_auto_ports (lft_session_params * sess, char *hostname, int init_dport)
2211 {
2212 /*
2213 * Provides rudimentary auto-select of source and destination ports
2214 * based on parsing the hostname supplied by the user
2215 *
2216 * EXPECTS a string like "mail.example.com" and RETURNS the
2217 * auto-selected src and dst ports if changed or NULL if unchanged
2218 *
2219 * Currently operates on user's input only as a call to
2220 * gethostbyaddr() before tracing could slow us down too much
2221 */
2222
2223 if (strlen(hostname) > 5) {
2224
2225 const char *mailservers[] = { "mail", "smtp", "mx", "relay", "inbound" };
2226 int cnt = 0;
2227 hostname = (char *) strtolower(hostname);
2228
2229 for (cnt = 0 ; cnt < 5 ; cnt++)
2230 {
2231 if (strstr(hostname,mailservers[cnt]))
2232 {
2233 sess->dport = 25;
2234 sess->sport = 25;
2235 break;
2236 }
2237 }
2238
2239 if (strncmp (hostname,"ftp",3) == 0) {
2240 sess->dport = 21;
2241 sess->sport = 19021;
2242 } else if (strncmp (hostname,"whois",5) == 0) {
2243 sess->dport = 43;
2244 sess->sport = 19043;
2245 } else if (strncmp (hostname,"imap",4) == 0) {
2246 sess->dport = 143;
2247 sess->sport = 19143;
2248 } else if (strncmp (hostname,"pop",3) == 0) {
2249 sess->dport = 110;
2250 sess->sport = 19110;
2251 } else if ((strncmp (hostname,"dns",3) == 0) || (strncmp (hostname,"ns",2) == 0) || (strncmp (hostname,"udns",4) == 0)) {
2252 sess->dport = 53;
2253 sess->sport = 53;
2254 } else if ((strncmp (hostname,"ntp",3) == 0) || (strncmp (hostname,"clock",5) == 0)) {
2255 sess->dport = 123;
2256 sess->sport = 123;
2257 }
2258
2259 if (sess->noisy && (sess->dport != init_dport))
2260 LFTEvtHandler(sess,EVT_AUTOCONFIGURED_TO_PORTS, NULL);
2261 }
2262 }
2263 /*---------------------------------------------------------------------------*/
2264 unsigned int
get_address(lft_session_params * sess,const char * host)2265 get_address(lft_session_params * sess, const char *host)
2266 {
2267 struct addrinfo hint, *ai;
2268 struct sockaddr_in addr;
2269
2270 /*
2271 * Check if this is numeric, if so simply convert.
2272 */
2273 if (inet_aton(host, &addr.sin_addr) == 1)
2274 return (addr.sin_addr.s_addr);
2275
2276 /*
2277 * This is a named host, look it up.
2278 */
2279 memset(&hint, 0, sizeof hint);
2280
2281 hint.ai_family = AF_INET;
2282
2283 if (getaddrinfo(host, NULL, &hint, &ai) != 0) {
2284 LFTErrHandler(sess, ERR_UNKNOWN_HOST, host);
2285 return (0);
2286 }
2287
2288 if (ai->ai_addrlen != sizeof addr) {
2289 /*
2290 * XXX
2291 * Is there a better error?
2292 */
2293 LFTErrHandler(sess, ERR_UNKNOWN_HOST, host);
2294 return (0);
2295 }
2296
2297 memcpy(&addr, ai->ai_addr, ai->ai_addrlen);
2298
2299 return (addr.sin_addr.s_addr);
2300 }
2301 /*---------------------------------------------------------------------------*/
2302 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
2303 /*
2304 The Windows/Cygwin version of this function uses the winsock built-in
2305 WSAIoctl SIO_ROUTING_INTERFACE_QUERY to find the appropriate interface.
2306 */
2307 static char *
lft_getifforremote(lft_session_params * sess,const char * remote)2308 lft_getifforremote(lft_session_params * sess, const char *remote)
2309 {
2310 struct sockaddr_in in, out;
2311 unsigned long nBytesReturned;
2312
2313 /* Only do this once of course */
2314 if (sock < 0) {
2315 if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
2316 LFTErrHandler(sess, WRN_GETIFFORREMOTE_SOCKET, NULL);
2317 if(sess->wsess != NULL) {
2318 free(sess->wsess);
2319 sess->wsess = NULL;
2320 }
2321 return NULL;
2322 }
2323 }
2324
2325 /* Ask what i/f the packet should go out on */
2326 in.sin_family = AF_INET;
2327 in.sin_port = 0;
2328 in.sin_addr.s_addr = get_address(sess, (char *)remote);
2329 if(sess->exit_state < 0){
2330 if(sess->wsess != NULL) {
2331 free(sess->wsess);
2332 sess->wsess = NULL;
2333 }
2334 return NULL;
2335 }
2336 if (SOCKET_ERROR != WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &in, sizeof(in), &out, sizeof(out), &nBytesReturned, NULL, NULL))
2337 return lft_getifname(out.sin_addr);
2338 /* not found */
2339 if(sess->wsess != NULL) {
2340 free(sess->wsess);
2341 sess->wsess = NULL;
2342 }
2343 return NULL;
2344 }
2345 #else
2346 /*
2347 The non-Windows version of this function uses connect() to
2348 acquire a (UDP) socket to the target and uses the OS's decision
2349 as to what interface is appropriate.
2350 */
2351 static char *
lft_getifforremote(lft_session_params * sess,const char * remote)2352 lft_getifforremote(lft_session_params * sess, const char *remote)
2353 {
2354 int sd;
2355 struct sockaddr_in sock;
2356 uint32_t socklen;
2357 uint16_t p1;
2358
2359 /* TODO: fill with a better RANDOM */
2360
2361 p1 = rand() % 33525 + 32525;
2362
2363 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
2364 {
2365 LFTErrHandler(sess, WRN_GETIFFORREMOTE_SOCKET, NULL);
2366 if(sess->wsess != NULL) {
2367 free(sess->wsess);
2368 sess->wsess = NULL;
2369 }
2370 return NULL;
2371 }
2372 sock.sin_family = AF_INET;
2373 sock.sin_addr.s_addr = get_address(sess, remote);
2374 if(sess->exit_state < 0){
2375 if(sess->wsess != NULL) {
2376 free(sess->wsess);
2377 sess->wsess = NULL;
2378 }
2379 return NULL;
2380 }
2381 sock.sin_port = htons(p1);
2382 if (connect(sd, (const struct sockaddr *)(const void *)&sock, sizeof sock) == -1)
2383 {
2384 LFTErrHandler(sess, WRN_GETIFFORREMOTE_CONNECT, NULL);
2385 #if defined(WIN32) || defined(_WIN32)
2386 closesocket(sd);
2387 #else
2388 close(sd);
2389 #endif
2390 if(sess->wsess != NULL) {
2391 free(sess->wsess);
2392 sess->wsess = NULL;
2393 }
2394 return NULL;
2395 }
2396
2397 socklen = sizeof sock;
2398 if (getsockname(sd, (struct sockaddr *)(void *)&sock, &socklen) == -1) {
2399 LFTErrHandler(sess, WRN_GETIFFORREMOTE_SOCKNAME, NULL);
2400 #if defined(WIN32) || defined(_WIN32)
2401 closesocket(sd);
2402 #else
2403 close(sd);
2404 #endif
2405 if(sess->wsess != NULL) {
2406 free(sess->wsess);
2407 sess->wsess = NULL;
2408 }
2409 return NULL;
2410 }
2411
2412 #if defined(WIN32) || defined(_WIN32)
2413 closesocket(sd);
2414 #else
2415 close(sd);
2416 #endif
2417
2418 return lft_getifname(sock.sin_addr);
2419 }
2420 #endif
2421 /*---------------------------------------------------------------------------*/
2422 static void
init_address(lft_session_params * sess,char * remote,const char * pcap_dev)2423 init_address (lft_session_params * sess, char *remote, const char *pcap_dev)
2424 {
2425
2426 (void)pcap_dev;
2427
2428 /* this is now set inside device selection routines */
2429 /* sess->local_address.s_addr = lft_getifaddr (pcap_dev); */
2430
2431 if (sess->noisy) {
2432 LFTEvtHandler(sess, EVT_ADDRESS_INITIALIZED, NULL);
2433 if(sess->exit_state < 0){
2434 if(sess->wsess != NULL) {
2435 free(sess->wsess);
2436 sess->wsess = NULL;
2437 }
2438 return;
2439 }
2440 }
2441
2442 sess->remote_address.s_addr = get_address(sess, remote);
2443 }
2444 /*---------------------------------------------------------------------------*/
2445 static void
open_sockets(lft_session_params * sess)2446 open_sockets (lft_session_params * sess)
2447 {
2448 struct timeval tforid;
2449 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
2450 int optval = 1;
2451 DWORD dwBytesRet = 2048;
2452 int rmem = 120832;
2453 int wmem = 120832;
2454 BOOL blnFlag=TRUE;
2455 int ioctlret;
2456 #endif
2457 #ifdef IP_HDRINCL
2458 int on = 1;
2459 #endif
2460 int i;
2461 #if defined(sun) || defined(__CYGWIN__) || defined( WIN32 ) || defined(_WIN32)
2462 struct sockaddr_in local_bind;
2463 #endif
2464
2465 #if defined(sun)
2466 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_IP);
2467 #elif defined(BSD_IP_STACK)
2468 switch(sess->protocol)
2469 {
2470 case 0: /*TCP*/
2471 case 4: /*TCP basic*/
2472 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
2473 break;
2474 case 1: /*UDP*/
2475 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
2476 break;
2477 case 2: /*ICMP basic*/
2478 case 3: /*RFC1393*/
2479 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
2480 break;
2481 }
2482 #elif defined(__CYGWIN__) || defined( WIN32 ) || defined(_WIN32)
2483 switch(sess->protocol)
2484 {
2485 case 0: /*TCP*/
2486 case 1: /*UDP*/
2487 case 4: /*TCP basic*/
2488 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
2489 break;
2490 case 2: /*ICMP basic*/
2491 case 3: /*RFC1393*/
2492 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
2493 break;
2494 }
2495 sess->recv_sock = socket (PF_INET, SOCK_RAW, IPPROTO_IP);
2496
2497 if (sess->recv_sock < 0) {
2498 LFTErrHandler(sess, ERR_RAW_SOCKET, NULL);
2499 return;
2500 }
2501 local_bind.sin_addr = sess->local_address;
2502 local_bind.sin_port = 0;
2503 local_bind.sin_family = AF_INET;
2504 if (bind(sess->recv_sock, (const struct sockaddr *)(const void *)&local_bind, sizeof(local_bind)) < 0) {
2505 LFTErrHandler(sess, ERR_SOCKET_BIND, NULL);
2506 return;
2507 }
2508 /* apparently the cygwin include files don't define this: */
2509 #ifndef SIO_RCVALL
2510 # define SIO_RCVALL 0x98000001
2511 #endif
2512 ioctlret = WSAIoctl(sess->recv_sock, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL, NULL);
2513 if (ioctlret < 0)
2514 {
2515 LFTErrHandler(sess, WRN_WSAIOCTL, NULL);
2516 if(sess->exit_state<0)
2517 return;
2518 }
2519 #else
2520 switch(sess->protocol)
2521 {
2522 case 0: /*TCP*/
2523 case 1: /*UDP*/
2524 case 4: /*TCP basic*/
2525 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
2526 break;
2527 case 2: /*ICMP basic*/
2528 case 3: /*RFC1393*/
2529 sess->send_sock = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
2530 break;
2531 }
2532 #endif
2533 if (sess->send_sock < 0) {
2534 LFTErrHandler(sess, ERR_RAW_SOCKET, NULL);
2535 if(sess->wsess) {
2536 free(sess->wsess);
2537 sess->wsess = NULL;
2538 }
2539 return;
2540 }
2541 #ifdef IP_HDRINCL
2542 if (setsockopt (sess->send_sock, IPPROTO_IP, IP_HDRINCL, (char *) &on, sizeof (on)) < 0) {
2543 LFTErrHandler(sess, ERR_IP_HDRINCL, NULL);
2544 return;
2545 }
2546 #endif
2547 #ifdef sun
2548 local_bind.sin_addr = sess->local_address;
2549 local_bind.sin_port = 0;
2550 local_bind.sin_family = AF_INET;
2551 if (bind (sess->send_sock, (const struct sockaddr *)&local_bind, sizeof (local_bind)) < 0) {
2552 LFTErrHandler(sess, ERR_SOCKET_BIND, NULL);
2553 return;
2554 }
2555 #endif
2556 #ifndef IPDEFTTL
2557 #define IPDEFTTL 200
2558 #endif
2559 /* if(sess->protocol==4)
2560 {
2561 if(sess->userlen == 0)
2562 sess->userlen=def_payload_len;
2563 if(!(sess->payload = malloc(sess->userlen)))
2564 {
2565 LFTErrHandler(sess, ERR_NOT_ENOUGH_MEM, NULL);
2566 return;
2567 }
2568 memset(sess->payload, 0,sess->userlen);
2569 sess->trace_packet.payload_len = sess->userlen;
2570 sess->payloadlen = sess->trace_packet.payload_len;
2571 sess->trace_packet.payload = sess->payload;
2572 }
2573 else */
2574 if(sess->protocol==2 || sess->protocol==3) /*ICMP base or ICMP RFC 1393*/
2575 {
2576 u_short ptr2id[sizeof tforid / sizeof (u_short)];
2577 u_short icmpid=0;
2578 unsigned int ptridx;
2579 gettimeofday(&tforid,NULL);
2580 memcpy(ptr2id, &tforid, sizeof ptr2id);
2581 for(ptridx=0;ptridx<sizeof(tforid)/sizeof(u_short);ptridx++)
2582 icmpid^=ptr2id[ptridx];
2583 generateICMPPacket(sess,
2584 LFTErrHandler,
2585 LFTEvtHandler,
2586 &sess->icmp_packet,
2587 1,
2588 ptr2id[0],
2589 1);
2590 }
2591 else /*TCP and UDP*/
2592 {
2593 /* Prepare the trace packet (probe) */
2594 memset (&(sess->trace_packet), 0, sizeof (sess->trace_packet));
2595
2596 if (sess->userlen == 0 && (sess->protocol==0 || sess->protocol==4)) {
2597 /* If user doesn't supply length, default to zero-payload for TCP packets */
2598 sess->trace_packet.payload_len = 0;
2599 sess->trace_packet.payload = NULL;
2600 }
2601 else if (sess->userlen == 0) {
2602 if(!(sess->payload = malloc(def_payload_len)))
2603 {
2604 LFTErrHandler(sess, ERR_NOT_ENOUGH_MEM, NULL);
2605 return;
2606 }
2607 memset(sess->payload, 0, def_payload_len);
2608 sess->trace_packet.payload_len = def_payload_len;
2609 } else {
2610 if (sess->hostname_lsrr_size > 0) {
2611 if (sess->protocol==1)
2612 sess->userlen -= (sizeof (struct ip) + sizeof(struct udphdr) + sess->trace_packet.lsrr.ipl_len + 1);
2613 else
2614 sess->userlen -= (sizeof (struct ip) + sizeof(struct tcphdr) + sess->trace_packet.lsrr.ipl_len + 1);
2615 } else {
2616 if (sess->protocol==1)
2617 sess->userlen -= (sizeof (struct ip) + sizeof(struct udphdr));
2618 else
2619 sess->userlen -= (sizeof (struct ip) + sizeof(struct tcphdr));
2620 }
2621 if (!(sess->payload = malloc(sess->userlen+4)))
2622 {
2623 LFTErrHandler(sess, ERR_NOT_ENOUGH_MEM, NULL);
2624 return;
2625 }
2626 memset(sess->payload, 0, sess->userlen+4);
2627 sess->trace_packet.payload_len = sess->userlen;
2628 }
2629
2630 sess->payloadlen = sess->trace_packet.payload_len;
2631 sess->trace_packet.payload = sess->payload;
2632
2633 /* set up initial ip headers, etc. */
2634
2635 if (sess->hostname_lsrr_size > 0) {
2636 for (i = 0; i < sess->hostname_lsrr_size; i++) {
2637 sess->trace_packet.lsrr.data[i] = get_address(sess, sess->hostname_lsrr[i]);
2638 if(sess->exit_state<0)
2639 {
2640 if(sess->payload)
2641 {
2642 free(sess->payload);
2643 sess->payload=NULL;
2644 }
2645 return;
2646 }
2647 }
2648 sess->trace_packet.lsrr.ipl_code = IPOPT_LSRR;
2649 sess->trace_packet.lsrr.ipl_len = sess->hostname_lsrr_size * 4 + 3;
2650 sess->trace_packet.lsrr.ipl_ptr = 4;
2651 }
2652 sess->trace_packet.ip_hdr.ip_v = 4;
2653 if (sess->hostname_lsrr_size > 0) {
2654 sess->trace_packet.ip_hdr.ip_hl = 6 + sess->hostname_lsrr_size; /* 5 + 3byte lsrr + addresses + padding */
2655 if (sess->protocol==1)
2656 sess->trace_packet.ip_hdr.ip_len = sizeof (struct ip) + sizeof(struct udphdr) + sess->trace_packet.lsrr.ipl_len + 1 + sess->trace_packet.payload_len;
2657 else
2658 sess->trace_packet.ip_hdr.ip_len = sizeof (struct ip) + sizeof(struct tcphdr) + sess->trace_packet.lsrr.ipl_len + 1 + sess->trace_packet.payload_len;
2659 } else {
2660 sess->trace_packet.ip_hdr.ip_hl = 5;
2661 if (sess->protocol==1)
2662 sess->trace_packet.ip_hdr.ip_len = sizeof (struct ip) + sizeof(struct udphdr) + sess->trace_packet.payload_len;
2663 else
2664 sess->trace_packet.ip_hdr.ip_len = sizeof (struct ip) + sizeof(struct tcphdr) + sess->trace_packet.payload_len;
2665 }
2666 sess->trace_packet.ip_hdr.ip_off = IP_DF;
2667
2668 #ifdef SCREWED_IP_LEN
2669 /* trace_packet.ip_hdr.ip_len = sizeof (struct ip) + sizeof(struct tcphdr); */
2670 #else
2671 sess->trace_packet.ip_hdr.ip_len = htons (sess->trace_packet.ip_hdr.ip_len);
2672 sess->trace_packet.ip_hdr.ip_off = htons(sess->trace_packet.ip_hdr.ip_off);
2673 #endif
2674 sess->trace_packet.ip_hdr.ip_ttl = IPDEFTTL;
2675 if (sess->protocol==1)
2676 sess->trace_packet.ip_hdr.ip_p = IPPROTO_UDP;
2677 else {
2678 sess->trace_packet.ip_hdr.ip_p = IPPROTO_TCP;
2679 if (sess->set_tos)
2680 sess->trace_packet.ip_hdr.ip_tos = TOSMINDELAY;
2681 sess->trace_packet.tcp_hdr.th_win = htons (sess->win_len);
2682 sess->trace_packet.tcp_hdr.th_off = sizeof (struct tcphdr) / 4;
2683 }
2684 }
2685
2686 /*
2687 * Init hop storage (array)
2688 * Init global packet info storage (SLIST)
2689 * Init per-hop packet info storage (SLIST)
2690 */
2691
2692 sess->hop_info = (struct hop_info_s *)malloc (sizeof(struct hop_info_s) * hop_info_size);
2693 for (i = 0; i < 256; i++) {
2694 memset(&(sess->hop_info[i]), 0, sizeof(struct hop_info_s));
2695 sess->hop_info[i].state = 0;
2696 sess->hop_info[i].done_packet = NULL;
2697 SLIST_INIT(&(sess->hop_info[i].packets));
2698 }
2699
2700 SLIST_INIT(&(sess->trace_packets));
2701 }
2702 /*---------------------------------------------------------------------------*/
2703 static unsigned int
send_packet(lft_session_params * sess,short nhop,unsigned short ttl,unsigned int seq,unsigned char flags)2704 send_packet (lft_session_params * sess, short nhop, unsigned short ttl, unsigned int seq, unsigned char flags)
2705 {
2706 struct sockaddr_in dest;
2707 unsigned int tseq=0;
2708 unsigned short tttl=0;
2709 struct sumh sum;
2710 char *buf;
2711 char *bptr = NULL;
2712 int blen = 0;
2713 char *s;
2714 EvtSentPacketParam espparam;
2715
2716 /* we'll use gettimeofday() from checktimeouts
2717 * instead of doing it again here */
2718 /* gettimeofday (&now, NULL); */
2719
2720 struct trace_packet_info_s *pinfo = NULL;
2721 struct trace_packet_s *packet = NULL;
2722
2723 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
2724 buf=(char *)_alloca(maxpacklen+64);
2725 #else
2726 buf=(char *)alloca(maxpacklen+64);
2727 #endif
2728
2729 if (!(pinfo = (struct trace_packet_info_s *)malloc(sizeof(struct trace_packet_info_s)))) {
2730 LFTErrHandler(sess, ERR_NOT_ENOUGH_MEM, NULL);
2731 return 0;
2732 }
2733
2734 memset(pinfo, 0, sizeof(struct trace_packet_info_s));
2735 packet = &(pinfo->u.packet);
2736 memcpy(packet, &(sess->trace_packet), sizeof(struct trace_packet_s));
2737
2738 bptr = buf;
2739
2740 dest.sin_family = AF_INET;
2741 dest.sin_addr = sess->remote_address;
2742 dest.sin_port = 0;
2743
2744 if (seq == 0)
2745 tseq = new_seq(sess);
2746 else
2747 tseq = seq;
2748
2749 if (nhop == -1)
2750 tttl = ttl;
2751 else
2752 tttl = nhop + 1;
2753
2754 /*There is no place we use this variable*/
2755 /*sess->num_sent++;*/
2756
2757 sess->ts_last_sent = sess->now;
2758
2759 packet->ip_hdr.ip_ttl = tttl;
2760 packet->ip_hdr.ip_src = sess->local_address;
2761 packet->ip_hdr.ip_dst = sess->remote_address;
2762
2763 espparam.flags=flags;
2764 espparam.nhop=nhop;
2765 espparam.tseq=tseq;
2766 espparam.tttl=tttl;
2767 if (sess->noisy > 1)
2768 {
2769 LFTEvtHandler(sess,EVT_SENT_PACKET, &espparam);
2770 if(sess->exit_state<0)
2771 {
2772 free(pinfo);
2773 return 0;
2774 }
2775 }
2776
2777 packet->ip_hdr.ip_sum = 0;
2778 #if !defined(SCREWED_IP_LEN)
2779 packet->ip_hdr.ip_sum = ip_cksum(&packet->ip_hdr);
2780 #endif
2781
2782 memcpy(bptr, &(packet->ip_hdr), sizeof(struct ip));
2783 bptr += sizeof(struct ip);
2784 if (packet->lsrr.ipl_len > 0) {
2785 memcpy(bptr, &(packet->lsrr), packet->lsrr.ipl_len + 1);
2786 bptr += (packet->lsrr.ipl_len + 1); /* PADDING !!! */
2787 }
2788
2789 /* Layer-4 preparation */
2790
2791 if (sess->protocol==1) {
2792
2793 if (sess->noisy > 5)
2794 {
2795 LFTEvtHandler(sess,EVT_SHOW_PAYLOAD, packet);
2796 if(sess->exit_state<0)
2797 {
2798 free(pinfo);
2799 return 0;
2800 }
2801 }
2802 /* Construct UDP (with payload) */
2803 packet->udp_hdr.uh_dport = htons(sess->dport + tttl);
2804 packet->udp_hdr.uh_sport = htons (sess->sport);
2805 packet->udp_hdr.uh_ulen = htons ((sizeof (struct udphdr)) + packet->payload_len);
2806 /* truncated-udplength 0
2807 packet->udp_hdr.uh_ulen = 0;
2808 packet->udp_hdr.th_flags = flags;
2809 */
2810
2811 /* create pseudo-header for checksum calculation */
2812 sum.src=sess->local_address.s_addr;
2813 sum.dst=sess->remote_address.s_addr;
2814 sum.fill=0;
2815 sum.protocol=IPPROTO_UDP;
2816 sum.len=htons(sizeof(struct udphdr) + packet->payload_len);
2817
2818 if(!( s = (char *)malloc(sizeof(struct sumh)+sizeof(struct udphdr)+packet->payload_len)))
2819 {
2820 LFTErrHandler(sess, ERR_NOT_ENOUGH_MEM, NULL);
2821 free(pinfo);
2822 return 0;
2823 }
2824 memset(s,0,(sizeof(struct sumh)+sizeof(struct udphdr)+packet->payload_len));
2825 memcpy(s,&sum,sizeof(struct sumh));
2826 memcpy(s+sizeof(struct sumh),&(packet->udp_hdr),sizeof(struct udphdr));
2827 memcpy(s+sizeof(struct sumh)+sizeof(struct udphdr),
2828 packet->payload,packet->payload_len);
2829
2830 packet->udp_hdr.uh_sum=udp_cksum((unsigned short *)(void *)s,
2831 sizeof(struct sumh)+sizeof(struct udphdr)+packet->payload_len);
2832 free(s);
2833
2834 if (sess->noisy > 5)
2835 {
2836 LFTEvtHandler(sess,EVT_SHOW_UDP_CHECKSUM, packet);
2837 if(sess->exit_state<0)
2838 {
2839 free(pinfo);
2840 return 0;
2841 }
2842 }
2843
2844 #if defined(SOLARIS_LENGTH_IN_CHECKSUM)
2845 packet->udp_hdr.uh_sum = htons (sizeof (struct udphdr) + packet->payload_len);
2846 #endif
2847 memcpy(bptr, &(packet->udp_hdr), sizeof(struct udphdr));
2848 bptr += sizeof(packet->udp_hdr);
2849 memcpy(bptr, packet->payload, packet->payload_len);
2850 blen = sizeof(struct ip) + packet->lsrr.ipl_len + sizeof(struct udphdr) + packet->payload_len;
2851 }
2852
2853 else {
2854 /* Construct TCP (no payload needed) */
2855 if (sess->noisy > 5)
2856 {
2857 LFTEvtHandler(sess,EVT_SHOW_PAYLOAD, packet);
2858 if(sess->exit_state<0)
2859 {
2860 free(pinfo);
2861 return 0;
2862 }
2863 }
2864 packet->tcp_hdr.th_dport = htons (sess->dport);
2865 /*
2866 trace_packet.tcp_hdr.th_seq = htonl (seq_start + trace_packet_info_length);
2867 */
2868 packet->tcp_hdr.th_seq = htonl (tseq);
2869 packet->tcp_hdr.th_sport = htons (sess->sport);
2870 packet->tcp_hdr.th_flags = flags;
2871
2872 #if defined(SOLARIS_LENGTH_IN_CHECKSUM)
2873 packet->tcp_hdr.th_sum = htons (sizeof (struct tcphdr)) + packet->payload_len;
2874 #else
2875 packet->tcp_hdr.th_sum = 0;
2876 packet->tcp_hdr.th_sum = tcp_cksum(&packet->ip_hdr, &packet->tcp_hdr, packet->payload, packet->payload_len);
2877 #endif
2878 if (sess->noisy > 5)
2879 {
2880 LFTEvtHandler(sess,EVT_SHOW_TCP_CHECKSUM, packet);
2881 if(sess->exit_state<0)
2882 {
2883 free(pinfo);
2884 return 0;
2885 }
2886 }
2887
2888 memcpy(bptr, &(packet->tcp_hdr), sizeof(struct tcphdr));
2889 bptr += sizeof(packet->tcp_hdr);
2890 memcpy(bptr, packet->payload, packet->payload_len);
2891 blen = sizeof(struct ip) + packet->lsrr.ipl_len + sizeof(struct tcphdr) + packet->payload_len;
2892 }
2893
2894 /* Packet is ready, fire away */
2895 if (sendto (sess->send_sock, buf, blen, 0, (const struct sockaddr *)(const void *)&dest, sizeof (dest)) < 0) {
2896 LFTErrHandler(sess, ERR_RAW_TCP_DISABLED, NULL);
2897 free(pinfo);
2898 return 0;
2899 }
2900 pinfo->hopno = nhop;
2901 if (sess->protocol==1)
2902 pinfo->seq = sess->dport + tttl;
2903 else if(!sess->protocol)
2904 pinfo->seq = tseq;
2905 pinfo->sent = sess->now;
2906 SLIST_INSERT_HEAD(&(sess->trace_packets), pinfo, next);
2907 sess->trace_packets_num++;
2908
2909 if (nhop != -1) {
2910 SLIST_INSERT_HEAD(&(sess->hop_info[nhop].packets), pinfo, next_by_hop);
2911 sess->hop_info[nhop].num_sent++;
2912 sess->hop_info[nhop].all_sent++;
2913 sess->hop_info[nhop].ts_last_sent = sess->now;
2914 }
2915
2916 return tseq;
2917 }
2918 /*---------------------------------------------------------------------------*/
2919 static unsigned int
send_hop(lft_session_params * sess,short nhop)2920 send_hop (lft_session_params * sess, short nhop)
2921 {
2922 WrnBadHopStateParam wbhsp;
2923 struct hop_info_s *h = &(sess->hop_info[nhop]);
2924
2925 if (!sess->adaptive)
2926 return send_packet (sess, nhop , 0, 0, sess->tcp_flags);
2927
2928 if (h->state == HS_SEND_FIN) {
2929 return send_packet(sess, nhop, 0, 0, TH_FIN);
2930 }
2931
2932 if (h->state == HS_SEND_SYN) {
2933 return send_packet(sess, nhop, 0, 0, TH_SYN);
2934 }
2935
2936 if (h->state == HS_SEND_SYN_ACK) {
2937 return send_packet(sess, nhop, 0, 0, HS_SEND_SYN_ACK);
2938 }
2939
2940 wbhsp.h=h;
2941 wbhsp.nhop=nhop;
2942 LFTErrHandler(sess, WRN_BAD_HOP_STATE, &wbhsp);
2943 return -1;
2944 }
2945 /*---------------------------------------------------------------------------*/
hop_state_up(lft_session_params * sess,short nhop)2946 int hop_state_up (lft_session_params * sess, short nhop)
2947 {
2948 struct hop_info_s *h = &(sess->hop_info[nhop]);
2949
2950 if (h->state == HS_MAX)
2951 return -1;
2952
2953 /* 1st try FIN, then SYN_ACK, then SYN, then fail (set to MAX) */
2954 if (h->state == HS_SEND_FIN)
2955 h->state = HS_SEND_SYN_ACK;
2956 else if (h->state == HS_SEND_SYN_ACK)
2957 h->state = HS_SEND_SYN;
2958 else
2959 h->state = HS_MAX;
2960
2961 h->num_sent = 0; /* for this state that is */
2962 return 0;
2963 }
2964 /*---------------------------------------------------------------------------*/
hop_state_copy(lft_session_params * sess,short nhop)2965 int hop_state_copy(lft_session_params * sess, short nhop)
2966 {
2967 int i;
2968
2969 if (sess->noisy > 4)
2970 LFTEvtHandler(sess,EVT_SHOW_HOPS, &nhop);
2971 if(sess->exit_state>=0)
2972 {
2973 for (i = (nhop+1); i <= 255; i++)
2974 if (sess->hop_info[i].state < sess->hop_info[nhop].state) {
2975 sess->hop_info[i].state = sess->hop_info[nhop].state;
2976 sess->hop_info[i].num_sent = 0;
2977 }
2978 }
2979
2980 return 0;
2981 }
2982 /*---------------------------------------------------------------------------*/
2983 static void
finish(lft_session_params * sess)2984 finish (lft_session_params * sess)
2985 {
2986 int hopno;
2987 int maxhop;
2988 int reply, noreply;
2989 int as_for_hop = 0;
2990 struct trace_packet_info_s *tp;
2991 char *netname;
2992 /*int ocres;*/
2993 char *myApp = (char *)malloc((strlen(version)+1 * sizeof(char)) + (strlen(appname) * sizeof(char)));
2994 struct ip_list_array *ipaslist = (struct ip_list_array *)malloc(sizeof(struct ip_list_array));
2995 /* Variables for seam detection */
2996 int icmpcode;
2997 int asseam_hopno=-1;
2998 struct in_addr asseam_hopaddr;
2999 int netseam_hopno=-1;
3000 struct in_addr netseam_hopaddr;
3001 struct in_addr classbmask;
3002 struct in_addr masked_target;
3003 int prevasn=-1;
3004 struct in_addr prevasn_hopaddr;
3005 int prevasn_hopno;
3006 int lastishole;
3007 int netreached=0;
3008 int isseam;
3009 /* ---------------------------- */
3010 inet_aton("255.255.0.0", &classbmask);
3011 masked_target.s_addr=sess->remote_address.s_addr & classbmask.s_addr;
3012
3013 EvtPacketInfoParam ehip;
3014
3015 memset(ipaslist, 0, sizeof(struct ip_list_array));
3016 memset(&tbuf, 0, sizeof(tbuf));
3017 gettimeofday (&(sess->trace_done_time), NULL);
3018 /*if(sess->protocol==0)
3019 {
3020 ocres = open_check(sess, LFTErrHandler, LFTEvtHandler);
3021 LFTEvtHandler(sess,EVT_OPEN_CHECK_RESULT,&ocres);
3022 if(ocres==1)
3023 {
3024 sess->target_open=1;
3025 sess->target_filtered=0;
3026 }
3027 else
3028 {
3029 sess->target_open=0;
3030 if(ocres<0)
3031 sess->target_filtered=0;
3032 else
3033 sess->target_filtered=1;
3034 }
3035 }*/
3036 if (sess->noisy > 3)
3037 {
3038 LFTEvtHandler(sess, EVT_SHOW_NUM_HOPS, NULL);
3039 if(sess->exit_state < 0)
3040 {
3041 free(ipaslist);
3042 free(myApp);
3043 return;
3044 }
3045 }
3046 if (sess->num_hops) {
3047 maxhop = sess->num_hops;
3048 /* display all packets we received from this host */
3049 SLIST_FOREACH(tp, &(sess->trace_packets), next)
3050 if (tp->is_done)
3051 tp->hopno = maxhop;
3052 } else {
3053 maxhop = sess->hop_info_length - 1;
3054 }
3055
3056 LFTEvtHandler(sess, EVT_TRACE_COMPLETED, NULL);
3057 if(sess->exit_state < 0)
3058 {
3059 free(ipaslist);
3060 free(myApp);
3061 return;
3062 }
3063
3064 /* if user wants ASN resolution from pwhois/cymru/riswhois, do it in bulk */
3065 if (sess->do_aslookup || sess->do_netlookup) {
3066 if(sess->noisy > 1)
3067 {
3068 LFTEvtHandler(sess,EVT_ON_RESOLUTION, NULL);
3069 if(sess->exit_state < 0)
3070 {
3071 free(ipaslist);
3072 free(myApp);
3073 return;
3074 }
3075 }
3076 if (!sess->use_radb) {
3077 /* populate bulk ip_addr_list structure */
3078 for (hopno = sess->ttl_min; hopno <= maxhop; hopno++) {
3079 SLIST_FOREACH(tp, &(sess->hop_info[hopno].packets), next_by_hop) {
3080 if (tp->recv.tv_usec) {
3081 (*ipaslist).ipaddr[as_for_hop] = tp->hopaddr;
3082 as_for_hop++;
3083 (*ipaslist).numItems = (as_for_hop);
3084 break;
3085 }
3086 }
3087 }
3088 if (sess->use_cymru) { /* use cymru bulk service */
3089 if (w_lookup_as_cymru_bulk(sess->wsess, &(*ipaslist)) != 0)
3090 if (sess->noisy) LFTErrHandler(sess, WRN_NS_LOOKUP_FAILED, NULL);
3091 } else if (sess->use_ris) { /* use RIPE NCC RIS service */
3092 if (w_lookup_all_riswhois_bulk(sess->wsess, &(*ipaslist)) != 0)
3093 if (sess->noisy) LFTErrHandler(sess, WRN_NS_LOOKUP_FAILED, NULL);
3094 } else { /* use pwhois bulk service */
3095 if ((strlen(version) * sizeof(char)) + 1 + (strlen(appname) * sizeof(char)) < 254) {
3096 *myApp = '\0';
3097 strcat(myApp, appname);
3098 strcat(myApp, " ");
3099 strcat(myApp, version);
3100 strncpy((*ipaslist).application,myApp,511);
3101 }
3102 if (w_lookup_all_pwhois_bulk(sess->wsess, &(*ipaslist)) != 0)
3103 if (sess->noisy)
3104 LFTErrHandler(sess, WRN_NS_LOOKUP_FAILED, NULL);
3105 }
3106 if(sess->exit_state < 0)
3107 {
3108 free(ipaslist);
3109 free(myApp);
3110 return;
3111 }
3112 }
3113 }
3114
3115 free(myApp);
3116
3117 if(sess->protocol == 1)
3118 sess->dport++;
3119 LFTEvtHandler(sess,EVT_TRACE_REPORT_START, &maxhop);
3120 if(sess->exit_state < 0){
3121 free(ipaslist);
3122 return;
3123 }
3124
3125 /* seam detection */
3126 as_for_hop=0;
3127 for(hopno = sess->ttl_min; hopno < sess->hop_info_length; hopno++)
3128 {
3129 struct in_addr last_hop;
3130 icmpcode=-100;
3131 last_hop.s_addr = 0;
3132 if(sess->hop_info[hopno].all_rcvd)
3133 {
3134 lastishole=0;
3135 SLIST_FOREACH(tp, &(sess->hop_info[hopno].packets), next_by_hop)
3136 {
3137 if(tp->recv.tv_sec)
3138 {
3139 if(hopno<=maxhop)
3140 icmpcode=tp->icmp_type;
3141 if(last_hop.s_addr != tp->hopaddr.s_addr)
3142 {
3143 if((tp->hopaddr.s_addr & classbmask.s_addr) == masked_target.s_addr)
3144 netreached=1;
3145 else
3146 {
3147 netseam_hopno=hopno;
3148 netseam_hopaddr=tp->hopaddr;
3149 }
3150 if(sess->do_aslookup || sess->do_netlookup)
3151 {
3152 if (sess->use_radb)
3153 {
3154 /* using RADB/IRR */
3155 tp->asnumber = w_lookup_as(sess->wsess, inet_ntoa(tp->hopaddr));
3156 }
3157 else
3158 {
3159 /* using pwhois by default */
3160 tp->asnumber = (*ipaslist).asn[as_for_hop];
3161 }
3162 if(prevasn==-1)
3163 {
3164 if(tp->asnumber)
3165 {
3166 prevasn=tp->asnumber;
3167 prevasn_hopno=hopno;
3168 prevasn_hopaddr=tp->hopaddr;
3169 }
3170 }
3171 else
3172 {
3173 if(tp->asnumber)
3174 {
3175 if(tp->asnumber!=prevasn)
3176 {
3177 asseam_hopno=prevasn_hopno;
3178 asseam_hopaddr=prevasn_hopaddr;
3179 }
3180 prevasn=tp->asnumber;
3181 prevasn_hopno=hopno;
3182 prevasn_hopaddr=tp->hopaddr;
3183 }
3184 }
3185 }
3186 last_hop=tp->hopaddr;
3187 }
3188 }
3189 }
3190 as_for_hop++;
3191 }
3192 else
3193 lastishole=1;
3194 if(icmpcode==-1)
3195 break;
3196 }
3197 if(!netreached)
3198 netseam_hopno=-1;
3199 if(lastishole)
3200 asseam_hopno=-1;
3201 /* -------------- */
3202 noreply = 0;
3203 reply = 0;
3204 as_for_hop = 0; /* this correlates the hopno to the asn stored in ipaslist */
3205
3206
3207 for (hopno = sess->ttl_min; hopno <= maxhop; hopno++) {
3208 struct in_addr last_hop;
3209
3210 if (sess->hop_info[hopno].all_rcvd != 0) {
3211 if (noreply >= 1)
3212 {
3213 EvtNoReplyParam nrp;
3214 nrp.hopno=hopno;
3215 nrp.noreply=noreply;
3216 LFTEvtHandler(sess,EVT_RPT_NO_REPLY, &nrp);
3217 if(sess->exit_state < 0)
3218 {
3219 free(ipaslist);
3220 return;
3221 }
3222 }
3223 }
3224
3225 last_hop.s_addr = 0;
3226 if ((sess->hop_info[hopno].state == HS_SEND_FIN) && (sess->hop_info[hopno+1].state == HS_SEND_SYN) && (sess->hop_info[hopno+1].ts_last_recv.tv_sec)) {
3227 LFTEvtHandler(sess,EVT_RPT_FRW_INSPECT_PACKS, NULL);
3228 if(sess->exit_state < 0){
3229 free(ipaslist);
3230 return;
3231 }
3232 }
3233
3234 if ((sess->hop_info[hopno].state != HS_SEND_SYN_ACK) && (sess->hop_info[hopno+1].state == HS_SEND_SYN_ACK) && (hopno == (sess->num_hops - 1))) {
3235 LFTEvtHandler(sess,EVT_RPT_FRW_STATE_FILTER, NULL);
3236 if(sess->exit_state < 0){
3237 free(ipaslist);
3238 return;
3239 }
3240 }
3241
3242 if ((sess->hop_info[hopno].flags & HF_ENDPOINT) && (noreply >= ((maxhop - sess->ttl_min)/2)) && sess->num_hops > 3) {
3243 LFTEvtHandler(sess,EVT_RPT_BSD_BUG, NULL);
3244 if(sess->exit_state < 0){
3245 free(ipaslist);
3246 return;
3247 }
3248 }
3249
3250 if (sess->hop_info[hopno].all_rcvd == 0) {
3251 reply = 0;
3252 } else {
3253 LFTEvtHandler(sess,EVT_RPT_HOP_INFO_START,&hopno);
3254 if(sess->exit_state < 0){
3255 free(ipaslist);
3256 return;
3257 }
3258
3259 SLIST_FOREACH(tp, &(sess->hop_info[hopno].packets), next_by_hop) {
3260
3261 if (tp->recv.tv_sec) {
3262 reply = 1;
3263
3264 if (last_hop.s_addr != tp->hopaddr.s_addr) {
3265 ehip.asnumber = 0; /* init/clear the ASN */
3266 if (sess->do_aslookup) {
3267 if (sess->use_radb) {
3268 /* using RADB/IRR */
3269 ehip.asnumber = w_lookup_as(sess->wsess, inet_ntoa(tp->hopaddr));
3270 } else {
3271 /* using pwhois by default */
3272 ehip.asnumber = (*ipaslist).asn[as_for_hop];
3273 }
3274 }
3275 tp->asnumber=ehip.asnumber;
3276 ehip.netname=NULL;
3277 if (sess->do_netlookup) {
3278 if (!sess->do_aslookup || (sess->do_aslookup && !sess->use_cymru && !sess->use_radb)) {
3279 netname = (*ipaslist).netName[as_for_hop];
3280 } else {
3281 netname = w_lookup_netname(sess->wsess, inet_ntoa(tp->hopaddr));
3282 }
3283 ehip.netname=netname;
3284 }
3285 if(ehip.netname)
3286 strncpy(tp->netname, ehip.netname, 511);
3287 else
3288 tp->netname[0]=0;
3289
3290 }
3291 ehip.last_hop=last_hop;
3292 tp->last_hop=ehip.last_hop;
3293 last_hop = tp->hopaddr;
3294 }
3295 ehip.tp=tp;
3296 /* seam processing */
3297 isseam=0;
3298 ehip.is_asseam=0;
3299 ehip.is_netseam=0;
3300 ehip.is_open=0;
3301 ehip.is_filtered=0;
3302 ehip.seam_traced=0;
3303 if(sess->check_seam && hopno==asseam_hopno && tp->hopaddr.s_addr==asseam_hopaddr.s_addr)
3304 {
3305 isseam=1;
3306 ehip.is_asseam=1;
3307 }
3308 if(sess->check_seam && hopno==netseam_hopno && tp->hopaddr.s_addr==netseam_hopaddr.s_addr)
3309 {
3310 isseam=1;
3311 ehip.is_netseam=1;
3312 }
3313 if(isseam)
3314 {
3315 if(sess->check_seam)
3316 {
3317 int curroutputstyle=global_output_style;
3318 char hostname[100];
3319 ehip.seam_traced=1;
3320 global_output_style=2;
3321 lft_session_params * subsess=LFTSessionOpen();
3322 strncpy(hostname, inet_ntoa(tp->hopaddr),100);
3323 subsess->senddevsel = sess->senddevsel;
3324 subsess->senddev = sess->senddev;
3325 subsess->auto_ports=0;
3326 subsess->dport=179;
3327 subsess->seq_start=30;
3328 subsess->retry_min=1;
3329 subsess->retry_max=1;
3330 subsess->resolve_names=0;
3331 subsess->ahead_limit=1;
3332 subsess->break_on_icmp = 0;
3333 subsess->is_graphviz_subquery=1;
3334 subsess->hostname=hostname;
3335 subsess->hostname_lsrr_size = 0;
3336 LFTExecute(subsess);
3337 ehip.is_open=subsess->target_open;
3338 ehip.is_filtered=subsess->target_filtered;
3339 LFTSessionClose(subsess);
3340 global_output_style=curroutputstyle;
3341 }
3342 }
3343 /* --------------- */
3344 LFTEvtHandler(sess,EVT_RPT_PACKET_INFO,&ehip);
3345 if(sess->exit_state < 0){
3346 free(ipaslist);
3347 return;
3348 }
3349 }
3350 LFTEvtHandler(sess,EVT_RPT_PACKET_LIST_END,NULL);
3351 if(sess->exit_state < 0){
3352 free(ipaslist);
3353 return;
3354 }
3355 }
3356 if (reply) {
3357 noreply = 0;
3358 as_for_hop++;
3359 } else
3360 noreply++;
3361
3362 reply = 0;
3363 } /* for(...) */
3364
3365 if (!sess->num_hops){
3366 LFTEvtHandler(sess, EVT_RPT_NO_HOPS, &maxhop);
3367 }
3368 if (sess->timetrace){
3369 LFTEvtHandler(sess, EVT_RPT_TIME_TRACE, NULL);
3370 }
3371 LFTEvtHandler(sess, EVT_ON_EXIT, NULL);
3372 free(ipaslist);
3373 return;
3374 }
3375
3376 /*---------------------------------------------------------------------------*/
check_timeouts(lft_session_params * sess)3377 static int check_timeouts (lft_session_params * sess)
3378 {
3379 int nhop;
3380 int need_reply = 0;
3381 int no_reply = 0;
3382 int last_return = 0;
3383
3384 gettimeofday (&(sess->now), NULL);
3385 if (timediff_ms (sess->ts_last_sent, sess->now) < sess->scatter_ms)
3386 return 0; /* not ready to send another packet yet */
3387
3388 for (nhop = sess->ttl_min; nhop < sess->hop_info_length; nhop++) {
3389 if (!sess->hop_info[nhop].num_sent) {
3390 send_hop(sess, nhop);
3391 return 0;
3392 }
3393 }
3394
3395 for (nhop = sess->ttl_min; nhop < sess->hop_info_length; nhop++) {
3396 if (sess->hop_info[nhop].num_sent <= sess->retry_max && !sess->hop_info[nhop].ts_last_recv.tv_sec) {
3397 if (sess->noisy > 4)
3398 {
3399 LFTEvtHandler(sess,EVT_TTL_NO_REPLY,&nhop);
3400 if(sess->exit_state<0)
3401 return 0;
3402 }
3403 if (timediff_ms (sess->hop_info[nhop].ts_last_sent, sess->now) >= sess->timeout_ms) {
3404 /* we timed out waiting for this hop -- retry if we have any
3405 * more tries */
3406 if (sess->hop_info[nhop].num_sent < sess->retry_max) {
3407 if (!sess->noisy && !sess->nostatus)
3408 LFTEvtHandler(sess,EVT_PROGRESS_NO_REPLY,NULL);
3409 if (sess->noisy > 2)
3410 LFTEvtHandler(sess,EVT_TTL_TOUT_RESEND,&nhop);
3411 if(sess->exit_state<0)
3412 return 0;
3413 send_hop(sess, nhop);
3414 return 0;
3415 } else {
3416 if (!sess->adaptive || hop_state_up(sess, nhop)) {
3417 if (sess->noisy > 3)
3418 LFTEvtHandler(sess,EVT_TTL_TOUT_GIVINGUP,&nhop);
3419 if(sess->exit_state<0)
3420 return 0;
3421 no_reply++;
3422 }
3423 }
3424 } else {
3425 need_reply++; /* we have to wait for this one to timeout */
3426 }
3427 } else { /* have reply */
3428 last_return = nhop;
3429 }
3430 }
3431
3432 if (sess->noisy > 4) {
3433 EvtDebugCheckpoint1Param edcp;
3434 edcp.last_return=last_return;
3435 edcp.need_reply=need_reply;
3436 edcp.no_reply=no_reply;
3437 LFTEvtHandler(sess,EVT_DBG_CHECKPOINT1,&edcp);
3438 if(sess->exit_state<0)
3439 return 0;
3440 }
3441 if (no_reply >= sess->ahead_limit) { /* we timed out. */
3442 if ((last_return + 3) * 2 < sess->hop_info_length) {
3443 if ((need_reply < 3) && (sess->num_rcvd < 2))
3444 LFTEvtHandler(sess,EVT_CANT_RELIABLY_RTRIP,NULL);
3445 if(sess->exit_state<0)
3446 return 0;
3447 finish (sess);
3448 return 1;
3449 }
3450 }
3451
3452 if ((!sess->num_hops || sess->hop_info_length < sess->num_hops || need_reply) && sess->hop_info_length < sess->ttl_limit) {
3453 if (sess->noisy > 4)
3454 LFTEvtHandler(sess,EVT_HAVE_UNANSWERRED_HOPS,NULL);
3455 if (need_reply >= sess->ahead_limit) {
3456 if (sess->noisy > 4)
3457 LFTEvtHandler(sess,EVT_TOO_FAR_AHEAD,NULL);
3458 return 0; /* wait for some replies before we go on */
3459 }
3460 if(sess->exit_state<0)
3461 return 0;
3462
3463 if (sess->num_hops > 0 && sess->hop_info_length >= sess->num_hops) {
3464 if (sess->noisy > 3)
3465 LFTEvtHandler(sess,EVT_HAVE_GAPS,NULL);
3466 return 0; /* we know how long the path is --
3467 * wait to fill in the blanks */
3468 }
3469
3470 nhop = sess->hop_info_length++;
3471 send_hop(sess, nhop);
3472 } else
3473 {
3474 if (sess->noisy >= 4)
3475 {
3476 LFTEvtHandler(sess,EVT_EITHER_RESP_OR_TOUT,NULL);
3477 if(sess->exit_state<0)
3478 return 0;
3479 }
3480 for (nhop = sess->ttl_min; nhop < sess->hop_info_length; nhop++)
3481 {
3482 if (sess->hop_info[nhop].num_sent < sess->retry_min && sess->hop_info[nhop].num_sent <= sess->retry_max)
3483 {
3484 send_hop(sess, nhop);
3485 return 0;
3486 }
3487 }
3488
3489 /* If we're adaptive and target appears closed, increment state and try again */
3490 if ((sess->adaptive) && (sess->target_open < 1) && (sess->hop_info[nhop].state != HS_MAX))
3491 {
3492 hop_state_up(sess, nhop);
3493 send_hop(sess, nhop);
3494 return 0;
3495 }
3496
3497 finish (sess);
3498 return 1;
3499 }
3500 return 0;
3501 }
3502 /*---------------------------------------------------------------------------*/
3503 static void
recv_packet(lft_session_params * sess,unsigned int seq,struct in_addr ipaddr,int icmp_type,const struct pcap_pkthdr * hdr)3504 recv_packet (lft_session_params * sess, unsigned int seq, struct in_addr ipaddr, int icmp_type, const struct pcap_pkthdr *hdr)
3505 {
3506 double ms;
3507 struct trace_packet_info_s *tp = NULL;
3508 EvtNonSeqPacketParam ensp;
3509
3510 /* Depending on the platform, we can use
3511 * the pcap header's timeval or we must call
3512 gettimeofday() for each packet */
3513
3514 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32) || defined( USE_GTOD )
3515 (void)hdr;
3516
3517 gettimeofday (&(sess->now), NULL);
3518 #else
3519 sess->now.tv_sec = hdr->ts.tv_sec;
3520 sess->now.tv_usec = hdr->ts.tv_usec;
3521 /* gettimeofday (&now, NULL); */
3522 #endif
3523
3524 /* First, search every probe to find an exact sequence match */
3525 SLIST_FOREACH(tp, &(sess->trace_packets), next) {
3526 if (tp->seq == seq) {
3527 break;
3528 }
3529 }
3530
3531 /* Next, if no probes have an exact sequence match, look for an unincremented ACK */
3532 if (tp == NULL) {
3533 if (sess->noisy > 3)
3534 {
3535 LFTEvtHandler(sess,EVT_LOOKFOR_UNINC_ACK,NULL);
3536 if(sess->exit_state<0)
3537 return;
3538 }
3539 SLIST_FOREACH(tp, &(sess->trace_packets), next) {
3540 if (((tp->seq) == (seq +1)) && (icmp_type == -1))
3541 break;
3542 }
3543 }
3544
3545 /* Next, if no probes have an exact sequence match, look for an off-by-len */
3546 if (tp == NULL) {
3547 if (sess->noisy > 3)
3548 {
3549 LFTEvtHandler(sess,EVT_LOOKFOR_OFF_BY_LEN,NULL);
3550 if(sess->exit_state<0)
3551 return;
3552 }
3553 SLIST_FOREACH(tp, &(sess->trace_packets), next) {
3554 if (((tp->seq) == (seq - sess->payloadlen)) && (icmp_type == -1))
3555 break;
3556 }
3557 }
3558
3559 /* Last resort. Catch any response from the target */
3560 if (tp == NULL) {
3561 if (sess->noisy > 3)
3562 {
3563 LFTEvtHandler(sess,EVT_LOOKFOR_LAST_RESORT,NULL);
3564 if(sess->exit_state<0)
3565 return;
3566 }
3567 SLIST_FOREACH(tp, &(sess->trace_packets), next) {
3568 /* Special case: look for a response to our SYN_ACK */
3569 if (tp->u.packet.tcp_hdr.th_flags == HS_SEND_SYN_ACK) {
3570 if (!tp->recv.tv_sec) {
3571 break;
3572 }
3573 }
3574 /* Truly the last resort: packet from the target with a wacky ACK sequence */
3575 if ((ipaddr.s_addr == sess->remote_address.s_addr) && (tp->hopaddr.s_addr == 0) && (icmp_type == -1)) {
3576 sess->target_anomaly = 1;
3577 }
3578 }
3579 }
3580
3581 /* This packet is not even close, drop it and move on */
3582 if (!tp) {
3583 if (sess->noisy)
3584 LFTEvtHandler(sess,EVT_SKIP_PACKET,NULL);
3585 else
3586 if (!sess->nostatus)
3587 LFTEvtHandler(sess,EVT_PROGRESS_SKIP_PACKET,NULL);
3588 return;
3589 }
3590
3591 if (tp->seq != seq) {
3592 ensp.ipaddr=ipaddr;
3593 ensp.tp=tp;
3594 if (((tp->seq) == (seq + 1)) && (icmp_type == -1)) {
3595 if (sess->noisy > 1) {
3596 LFTEvtHandler(sess,EVT_ACK_WAS_NOT_INC,&ensp);
3597 if(sess->exit_state<0)
3598 return;
3599 }
3600 /* return; */
3601 } else if (((tp->seq) == (seq - sess->payloadlen)) && (icmp_type == -1)) {
3602 if (sess->noisy > 1) {
3603 LFTEvtHandler(sess,EVT_RST_REL_TO_ISN,&ensp);
3604 if(sess->exit_state<0)
3605 return;
3606 }
3607 /* return; */
3608 } else if ((ipaddr.s_addr == sess->remote_address.s_addr) && (icmp_type == -1)) {
3609 if (sess->noisy > 1) {
3610 LFTEvtHandler(sess,EVT_ACK_WAS_WAY_OFF,&ensp);
3611 if(sess->exit_state<0)
3612 return;
3613 }
3614 /* return; */
3615 }
3616 }
3617
3618 if (tp->recv.tv_sec) {
3619 if (sess->noisy)
3620 LFTEvtHandler(sess,EVT_DUPLICATE_PACKET, NULL);
3621 else
3622 if (!sess->nostatus)
3623 LFTEvtHandler(sess,EVT_PROGRESS_DUPLICATE,NULL);
3624 return;
3625 }
3626
3627 if (sess->noisy > 1)
3628 {
3629 EvtRecvPacketParam erpp;
3630 erpp.ipaddr=ipaddr;
3631 erpp.seq=seq;
3632 erpp.tp=tp;
3633 LFTEvtHandler(sess,EVT_RECV_PACKET,&erpp);
3634 }
3635 else {
3636 if (!sess->nostatus)
3637 LFTEvtHandler(sess,EVT_PROGRESS_OK,NULL);
3638 }
3639 if(sess->exit_state<0)
3640 return;
3641
3642 /* increment received packet counter */
3643 sess->num_rcvd++;
3644
3645 tp->recv = sess->now;
3646 if (tp->hopno != -1) {
3647 sess->hop_info[tp->hopno].ts_last_recv = sess->now;
3648 sess->hop_info[tp->hopno].all_rcvd++;
3649 hop_state_copy(sess, tp->hopno);
3650 /* indicate this hop has a sequence anomaly */
3651
3652 if (icmp_type == -1)
3653 sess->hop_info[tp->hopno].flags |= HF_ENDPOINT;
3654 }
3655
3656 tp->hopaddr = ipaddr;
3657 tp->icmp_type = icmp_type;
3658 if (icmp_type != -2 && (!sess->num_hops || sess->num_hops > tp->hopno))
3659 if (sess->break_on_icmp || (icmp_type == -1)) {
3660 if (tp->hopno != -1) { /* we set fake type -1 when we get actual
3661 * tcp packet in return - meaning destination */
3662 sess->num_hops = tp->hopno;
3663 tp->is_done = 1;
3664 if (sess->noisy > 1 && sess->target_open < 1)
3665 LFTEvtHandler(sess,EVT_TCP_PORT_CLOSED,NULL);
3666 else
3667 if (sess->noisy > 1 && sess->target_open > 0)
3668 LFTEvtHandler(sess,EVT_TCP_PORT_OPEN,NULL);
3669 if(sess->exit_state<0)
3670 return;
3671 }
3672 }
3673
3674 /* adjust scatter if we have fast reply times */
3675 ms = timediff_ms (tp->sent, tp->recv);
3676 sess->scatter_ms = (sess->scatter_ms * (sess->ahead_limit - 1) + ms) / sess->ahead_limit;
3677
3678 }
3679 /*---------------------------------------------------------------------------*/
lft_printf(lft_session_params * sess,const char * templ,...)3680 void lft_printf(lft_session_params * sess, const char *templ, ...)
3681 {
3682 va_list ap;
3683 char buf[1024];
3684
3685 va_start (ap, templ);
3686 vsprintf(buf, templ, ap);
3687 va_end (ap);
3688 LFTEvtHandler(sess, EVT_DBG_LOG_MESSAGE, buf);
3689 }
3690 /*---------------------------------------------------------------------------*/
process_packet(lft_session_params * sess,const u_char * packet,const struct pcap_pkthdr * hdr)3691 static void process_packet (lft_session_params * sess, const u_char *packet, const struct pcap_pkthdr *hdr)
3692 {
3693 const struct ether_header *eptr;
3694 const struct ip *ip, *orig_ip;
3695 const struct tcphdr *tcp;
3696 const struct udphdr *udp;
3697 const struct icmp *icmp;
3698
3699 if (sess->noisy > 4)
3700 {
3701 LFTEvtHandler(sess,EVT_PROCESS_PACKET_START,NULL);
3702 if(sess->exit_state<0)
3703 return;
3704 }
3705 check_timeouts (sess);
3706 if(sess->exit_state<0)
3707 return;
3708
3709 /* Test EtherType to adjust Ethernet header length
3710 802.1q VLAN Ethernet frame (dot1q) */
3711 eptr = (const struct ether_header *) packet;
3712 if ((sess->skip_header_len == sizeof (struct ether_header)) && (ntohs (eptr->ether_type) == ETHERTYPE_VLAN)) {
3713 sess->skip_header_len += 4;
3714 }
3715
3716 packet += sess->skip_header_len;
3717 ip = (const void *)packet;
3718
3719 packet += 4 * ip->ip_hl;
3720
3721 switch (ip->ip_p) {
3722 case IPPROTO_ICMP:
3723 orig_ip = ip;
3724 icmp = (const void *)packet;
3725 if (icmp->icmp_type != ICMP_UNREACH && icmp->icmp_type != ICMP_TIMXCEED) {
3726 return;
3727 }
3728 ip = &icmp->icmp_ip;
3729 if (sess->protocol==1) {
3730 if (ip->ip_p != IPPROTO_UDP)
3731 return; /* not a response to our udp probe */
3732 } else {
3733 if (ip->ip_p != IPPROTO_TCP)
3734 return; /* not a response to our tcp probe */
3735 }
3736 packet = (const u_char *)ip;
3737 packet += 4 * ip->ip_hl;
3738
3739 if (sess->protocol==1) {
3740 udp = (const void *)packet;
3741 if (ntohs (udp->uh_sport) != sess->sport || ip->ip_src.s_addr != sess->local_address.s_addr || ip->ip_dst.s_addr != sess->remote_address.s_addr) {
3742 LFTEvtHandler(sess,EVT_UDP_NOT_FOR_US,NULL);
3743 return; /* not for us */
3744 }
3745 if (sess->noisy > 2) {
3746 EvtIncomingICMPUDPParam eiiup;
3747 eiiup.icmp=icmp;
3748 eiiup.ip=ip;
3749 eiiup.orig_ip=orig_ip;
3750 eiiup.udp=udp;
3751 LFTEvtHandler(sess,EVT_INCOMING_ICMP_UDP,&eiiup);
3752 if(sess->exit_state<0)
3753 return;
3754 }
3755 if (sess->noisy > 1)
3756 {
3757 LFTEvtHandler(sess,EVT_RCVD_ICMP_UDP,udp);
3758 if(sess->exit_state<0)
3759 return;
3760 }
3761 recv_packet (sess, ntohs (udp->uh_dport) , orig_ip->ip_src,
3762 (icmp->icmp_type == ICMP_TIMXCEED) ? -2 : icmp->icmp_code, hdr);
3763 if(sess->exit_state<0)
3764 return;
3765 } else {
3766 tcp = (const void *)packet;
3767 if (ntohs (tcp->th_dport) != sess->dport || ip->ip_src.s_addr != sess->local_address.s_addr || ip->ip_dst.s_addr != sess->remote_address.s_addr)
3768 return; /* not for us */
3769 if (sess->noisy > 2) {
3770 EvtIncomingICMPTCPParam eiitp;
3771 eiitp.icmp=icmp;
3772 eiitp.ip=ip;
3773 eiitp.orig_ip=orig_ip;
3774 eiitp.tcp=tcp;
3775 LFTEvtHandler(sess,EVT_INCOMING_ICMP_TCP,&eiitp);
3776 if(sess->exit_state<0)
3777 return;
3778 }
3779 if (sess->noisy > 1)
3780 {
3781 LFTEvtHandler(sess,EVT_RCVD_ICMP_TCP,tcp);
3782 if(sess->exit_state<0)
3783 return;
3784 }
3785 recv_packet (sess, ntohl (tcp->th_seq) , orig_ip->ip_src,
3786 (icmp->icmp_type == ICMP_TIMXCEED) ? -2 : icmp->icmp_code, hdr);
3787 if(sess->exit_state<0)
3788 return;
3789 }
3790 return;
3791
3792 case IPPROTO_TCP:
3793 /* check for RST reply */
3794 tcp = (const void *)packet;
3795 if (!(tcp->th_flags & TH_RST) && !(tcp->th_flags & TH_ACK) && !(tcp->th_flags & TH_SYN))
3796 return; /* not what we're looking for */
3797
3798 if (ntohs (tcp->th_sport) != sess->dport || ip->ip_src.s_addr != sess->remote_address.s_addr || ip->ip_dst.s_addr != sess->local_address.s_addr) {
3799 return; /* not the right connection */
3800 }
3801
3802 if (sess->noisy > 1) {
3803 LFTEvtHandler(sess,EVT_RCVD_TCP,tcp);
3804 if(sess->exit_state<0)
3805 return;
3806 }
3807
3808 /*if (ntohl(tcp->th_ack) < seq_start || ntohl(tcp->th_ack) > seq_start + trace_packet_info_length + 1)
3809 return; * not for us */
3810
3811 /* Check for SYN,ACK in response to determine if target is listening */
3812 if ((tcp->th_flags & TH_ACK) && (tcp->th_flags & TH_SYN) && !(tcp->th_flags & TH_RST))
3813 {
3814 sess->target_open++;
3815 }
3816 /* It's wrong, because it can reset status of port after it already detected as open
3817 if ((tcp->th_flags & TH_ACK) && !(tcp->th_flags & TH_SYN) && (tcp->th_flags & TH_RST))
3818 {
3819 sess->target_open = 0;
3820 }
3821 */
3822
3823 recv_packet (sess, ntohl (tcp->th_ack) - 1, ip->ip_src, -1, hdr);
3824 if(sess->exit_state<0)
3825 return;
3826 /*Could be nice to host and send a RESET here*/
3827 /*
3828 send_packet(-1, IPDEFTTL, ntohl(tcp->th_ack) + 1, TH_RST);
3829 */
3830 return;
3831
3832 case IPPROTO_UDP:
3833 /* could be a probe we sent or something we don't support */
3834 return;
3835
3836 default:
3837 if (sess->noisy > 3)
3838 LFTEvtHandler(sess,EVT_RCVD_UNKNOWN,ip);
3839 }
3840 }
3841 /*---------------------------------------------------------------------------*/
3842 #if !defined(__CYGWIN__) && !defined(WIN32) && !defined(_WIN32)
3843 static void
pcap_process_packet(u_char * user_data,const struct pcap_pkthdr * hdr,const u_char * packet)3844 pcap_process_packet (u_char * user_data, const struct pcap_pkthdr *hdr,
3845 const u_char * packet)
3846 {
3847 lft_session_params * sess=(lft_session_params *)(void *)user_data;
3848 if(sess->exit_state<0)
3849 return;
3850 process_packet(sess, packet, hdr);
3851 }
3852 #endif
3853 /*---------------------------------------------------------------------------*/
3854 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
cygwin_process(lft_session_params * sess)3855 void cygwin_process(lft_session_params * sess)
3856 {
3857 fd_set fds;
3858 struct timeval tm;
3859 int wsaerr;
3860 tm.tv_sec = 0;
3861 tm.tv_usec = 100000;
3862
3863 FD_ZERO(&fds);
3864 FD_SET(sess->recv_sock, &fds);
3865 if (select(sess->recv_sock+1, &fds, 0, 0, &tm) < 0) {
3866 wsaerr=WSAGetLastError();
3867 LFTErrHandler(sess, ERR_WIN_SELECT, NULL);
3868 return;
3869 }
3870 if (FD_ISSET(sess->recv_sock, &fds)) {
3871 /* read packet */
3872 char packetbuf[2048];
3873 int nread;
3874 memset(packetbuf, 0, sizeof(packetbuf));
3875 nread = recv(sess->recv_sock, packetbuf, sizeof(packetbuf), 0);
3876 if (nread <= 0) {
3877 LFTErrHandler(sess, ERR_WIN_RECV, NULL);
3878 return;
3879 }
3880 process_packet(sess, packetbuf, NULL);
3881 }
3882 }
3883
3884 #endif
3885 /*---------------------------------------------------------------------------*/
3886 /* Replacement for deprecated pcap_lookupdev */
3887 /*---------------------------------------------------------------------------*/
lft_pcap_lookupdev(char * ebuf)3888 char * lft_pcap_lookupdev(char *ebuf)
3889 {
3890 pcap_if_t *alldevs;
3891 int res = pcap_findalldevs(&alldevs, ebuf);
3892 if(!res)
3893 return alldevs->name;
3894 return NULL;
3895 }
3896 /*---------------------------------------------------------------------------*/
3897 /* Main of lft */
3898 /*---------------------------------------------------------------------------*/
LFTExecute(lft_session_params * sess)3899 void LFTExecute(lft_session_params * sess)
3900 {
3901 #if !defined(__CYGWIN__) && !defined(WIN32) && !defined(_WIN32)
3902 char ebuf[PCAP_ERRBUF_SIZE];
3903 /*static pcap_t *pd;*/
3904 #endif
3905
3906 sess->exit_state = 0;
3907 if(sess->auto_ports != 0)
3908 {
3909 do_auto_ports(sess, sess->hostname, sess->dport);
3910 if(sess->exit_state < 0){
3911 /* if(sess->hostname != NULL)
3912 free(sess->hostname); */
3913 if(sess->wsess != NULL) {
3914 free(sess->wsess);
3915 sess->wsess = NULL;
3916 }
3917 return;
3918 }
3919 }
3920
3921 if ((sess->do_netlookup != 0) || (sess->do_aslookup != 0))
3922 {
3923 sess->wsess = w_init(); /* initialize the whois framework */
3924 sess->wsess->logprintfCookie = sess; /*Parameter for lft_printf*/
3925 }
3926
3927 /* if not given network interface, select one automatically */
3928 if (!sess->userdevsel) {
3929 sess->pcap_dev = lft_getifforremote(sess, sess->hostname);
3930 if(sess->exit_state < 0){
3931 if(sess->wsess != NULL) {
3932 free(sess->wsess);
3933 sess->wsess = NULL;
3934 }
3935 /* if (sess->hostname != NULL)
3936 free(sess->hostname); */
3937 return;
3938 }
3939 #if !defined(__CYGWIN__) && !defined(WIN32) && !defined(_WIN32)
3940 if (sess->pcap_dev == NULL)
3941 sess->pcap_dev = lft_pcap_lookupdev (ebuf);
3942 if (sess->pcap_dev == NULL) {
3943 LFTErrHandler(sess, ERR_PCAP_ERROR, ebuf);
3944 if(sess->wsess != NULL) {
3945 free(sess->wsess);
3946 sess->wsess = NULL;
3947 }
3948 /* if (sess->hostname != NULL)
3949 free(sess->hostname); */
3950 return;
3951 }
3952 #else
3953 if (sess->pcap_dev == NULL) {
3954 LFTErrHandler(sess, ERR_DISCOVER_INTERFACE, NULL);
3955 if(sess->wsess != NULL) {
3956 free(sess->wsess);
3957 sess->wsess = NULL;
3958 }
3959 return;
3960 }
3961 #endif
3962 /* we have a receive device, set the source address */
3963 sess->pcap_send_dev = sess->pcap_dev;
3964 sess->local_address.s_addr = lft_getifaddr(sess->pcap_dev);
3965
3966 } else {
3967 struct in_addr addr;
3968 if (inet_aton(sess->userdev, &addr)) {
3969 /* specified by ip address -- look up device. */
3970 sess->pcap_dev = lft_getifname(addr);
3971 if (sess->pcap_dev != 0) {
3972 LFTErrHandler(sess, ERR_UNKNOWN_INTERFACE, NULL);
3973 if(sess->wsess != NULL) {
3974 free(sess->wsess);
3975 sess->wsess = NULL;
3976 }
3977 return;
3978 }
3979 /* we have a receive device, set the source address */
3980 sess->local_address.s_addr = lft_getifaddr(sess->pcap_dev);
3981 } else
3982 sess->pcap_dev = sess->userdev;
3983 sess->pcap_send_dev = sess->userdev;
3984 sess->local_address.s_addr = lft_getifaddr(sess->pcap_dev);
3985 };
3986
3987 /* if user wants a different/spoof interface, facilitate */
3988 if (sess->senddevsel > 0) {
3989 struct in_addr addr;
3990 if (inet_aton(sess->senddev, &addr)) {
3991 /* specified by ip address -- force using default device */
3992 /*sess->pcap_send_dev = lft_getifname(addr);*/
3993 sess->pcap_send_dev = lft_getifforremote(sess, sess->hostname);
3994 if (sess->pcap_send_dev == 0) {
3995 LFTErrHandler(sess, ERR_UNKNOWN_SEND_INTERFACE, NULL);
3996 return;
3997 }
3998 /* we have a send IP address, set the source address */
3999 sess->local_address.s_addr = get_address(sess,sess->senddev);
4000 } else {
4001 sess->pcap_send_dev = sess->senddev;
4002 if (sess->pcap_send_dev == 0) {
4003 LFTErrHandler(sess, ERR_UNKNOWN_SEND_INTERFACE, NULL);
4004 return;
4005 }
4006 /* we have a send device, set the source address */
4007 sess->local_address.s_addr = lft_getifaddr(sess->pcap_dev);
4008 }
4009 };
4010
4011 #if !defined(__CYGWIN__) && !defined(WIN32) && !defined(_WIN32)
4012 sess->pcapdescr = pcap_open_live (sess->pcap_dev, 1600, 0, 20, ebuf);
4013 /* retain and inform data link type */
4014 if (sess->pcapdescr == 0) {
4015 LFTErrHandler(sess, ERR_PCAP_DEV_UNAVAILABLE, ebuf);
4016 if(sess->wsess != NULL) {
4017 free(sess->wsess);
4018 sess->wsess = NULL;
4019 }
4020 return;
4021 }
4022 sess->pcap_datalink = pcap_datalink(sess->pcapdescr);
4023 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
4024 sess->skip_header_len = 0;
4025 #else
4026 /* use pcap datalink type to determine skip_header_len */
4027 if (sess->pcap_datalink == DLT_RAW)
4028 sess->skip_header_len = 0;
4029 else if (sess->pcap_datalink == DLT_PPP)
4030 sess->skip_header_len += 4;
4031 else if (sess->pcap_datalink == DLT_NULL)
4032 sess->skip_header_len += 4;
4033 else if (sess->pcap_datalink == DLT_PPP_ETHER)
4034 sess->skip_header_len += (8 + (sizeof (struct ether_header)));
4035 else if (sess->pcap_datalink == DLT_LINUX_SLL)
4036 sess->skip_header_len += 16;
4037 else /* assume ethernet: linktype EN10MB */
4038 sess->skip_header_len = sizeof (struct ether_header);
4039 /* if we're on what looks like a serial link, up the timeout (scatter will take care of itself) */
4040 /* if ((sess->pcap_datalink == DLT_PPP || sess->pcap_datalink == DLT_LINUX_SLL) && (sess->timeout_ms == DEFAULT_TIMEOUT_MS))
4041 sess->timeout_ms += 5000; */
4042 #endif
4043 if (sess->noisy)
4044 {
4045 LFTEvtHandler(sess,EVT_DEVICE_SELECTED,NULL);
4046 if(sess->exit_state < 0){
4047 if(sess->wsess != NULL) {
4048 free(sess->wsess);
4049 sess->wsess = NULL;
4050 }
4051 return;
4052 }
4053 }
4054 #ifdef BSD_IP_STACK
4055 #ifndef NETBSD
4056 uint32_t bpfimmflag = 1;
4057 /* Instruct device to return packets immediately */
4058 if (ioctl(pcap_fileno(sess->pcapdescr), BIOCIMMEDIATE, &bpfimmflag) < 0) {
4059 LFTErrHandler(sess, WRN_BIOCIMMEDIATE, pcap_strerror(errno));
4060 if(sess->exit_state < 0){
4061 if(sess->wsess != NULL) {
4062 free(sess->wsess);
4063 sess->wsess = NULL;
4064 }
4065 if(sess->pcapdescr != 0)
4066 {
4067 pcap_close(sess->pcapdescr);
4068 sess->pcapdescr=0;
4069 }
4070 return;
4071 }
4072 }
4073 #endif
4074 #endif
4075 /* Set pcap non-blocking mode */
4076 if (pcap_setnonblock(sess->pcapdescr, 1, ebuf) < 0) {
4077 LFTErrHandler(sess, ERR_PCAP_NONBLOCK_ERROR, ebuf);
4078 if(sess->exit_state < 0){
4079 if(sess->wsess != NULL) {
4080 free(sess->wsess);
4081 sess->wsess = NULL;
4082 }
4083 /* if(sess->hostname != NULL)
4084 free(sess->hostname); */
4085 return;
4086 }
4087 }
4088 #endif
4089
4090 if (sess->senddevsel > 0)
4091 init_address (sess, sess->hostname, sess->pcap_send_dev);
4092 else
4093 init_address (sess, sess->hostname, sess->pcap_dev);
4094 if(sess->exit_state < 0){
4095 if(sess->wsess != NULL) {
4096 free(sess->wsess);
4097 sess->wsess = NULL;
4098 }
4099 /* if(sess->hostname != NULL)
4100 free(sess->hostname); */
4101 return;
4102 }
4103
4104 if (!sess->seq_start && sess->protocol != 1) {
4105 sess->seq_start = rand();
4106 }
4107
4108 if (sess->noisy > 3 || (sess->noisy > 0 && sess->seq_start))
4109 {
4110 LFTEvtHandler(sess, EVT_SHOW_INITIAL_SEQNUM, NULL);
4111 if(sess->exit_state < 0){
4112 if(sess->wsess != NULL) {
4113 free(sess->wsess);
4114 sess->wsess = NULL;
4115 }
4116 /* if (sess->hostname != NULL)
4117 free(sess->hostname); */
4118 return;
4119 }
4120 }
4121
4122 open_sockets(sess);
4123 if(sess->exit_state < 0)
4124 {
4125 if(sess->send_sock > 0)
4126 {
4127 #if defined(WIN32) || defined(_WIN32)
4128 closesocket(sess->send_sock);
4129 #else
4130 close(sess->send_sock);
4131 #endif
4132 sess->send_sock = 0;
4133 }
4134 #if defined(WIN32) || defined(_WIN32)
4135 if(sess->recv_sock > 0)
4136 {
4137
4138 closesocket(sess->recv_sock);
4139 sess->recv_sock = 0;
4140 }
4141 #else
4142 if(sess->pcapdescr != 0)
4143 {
4144 pcap_close(sess->pcapdescr);
4145 sess->pcapdescr=0;
4146 }
4147 #endif
4148 return;
4149 }
4150
4151 #if !defined(__CYGWIN__) && !defined(WIN32) && !defined(_WIN32)
4152 #ifndef LFT_DONT_USE_SAFE_UID
4153 if(!sess->check_seam && !sess->is_graphviz_subquery)
4154 setuid (getuid ());
4155 #endif
4156 #endif
4157
4158 if (sess->adaptive) {
4159 if (sess->retry_min < 2)
4160 sess->retry_min = 2;
4161 }
4162
4163 if (sess->protocol==1) {
4164 if (sess->retry_min > 2)
4165 sess->retry_min = 2;
4166 }
4167
4168 if (sess->retry_max < sess->retry_min)
4169 sess->retry_max = sess->retry_min;
4170
4171 gettimeofday (&(sess->begin_time), NULL);
4172 LFTEvtHandler(sess,EVT_TRACE_START,NULL);
4173 if(sess->exit_state<0)
4174 {
4175 if(sess->send_sock > 0)
4176 {
4177 #if defined(WIN32) || defined(_WIN32)
4178 closesocket(sess->send_sock);
4179 #else
4180 close(sess->send_sock);
4181 #endif
4182 sess->send_sock = 0;
4183 }
4184 #if defined(WIN32) || defined(_WIN32)
4185 if(sess->recv_sock > 0)
4186 {
4187 closesocket(sess->recv_sock);
4188 sess->recv_sock = 0;
4189 }
4190 #endif
4191 return;
4192 }
4193 if(sess->protocol<2) /*UDP or TCP*/
4194 {
4195 #if defined( __CYGWIN__ ) || defined( WIN32 ) || defined(_WIN32)
4196 for (;;) {
4197 cygwin_process(sess);
4198 if(sess->exit_state<0)
4199 break;
4200 if(check_timeouts(sess))
4201 break;
4202 if(sess->exit_state<0)
4203 break;
4204 }
4205 #else
4206 while (pcap_dispatch (sess->pcapdescr, -1, pcap_process_packet, (u_char *)sess) >= 0) {
4207 if(sess->exit_state<0)
4208 break;
4209 if (sess->noisy > 6)
4210 {
4211 LFTEvtHandler(sess,EVT_DBG_CHECKPOINT2,NULL);
4212 if(sess->exit_state < 0)
4213 break;
4214 }
4215 if(check_timeouts (sess))
4216 break;
4217 if(sess->exit_state < 0)
4218 break;
4219 }
4220 #endif
4221 }
4222 else
4223 {
4224 if(sess->protocol<4)
4225 icmp_trace_main_loop(sess, LFTErrHandler, LFTEvtHandler); /*ICMP traces*/
4226 else
4227 tcp_base_trace_main_loop(sess, LFTErrHandler, LFTEvtHandler);
4228 }
4229 /*{
4230 int i;
4231 printf("\n");
4232 for(i=0;i<sess->debugmapidx;i++)
4233 {
4234 if(sess->debugmap[i].type)
4235 {
4236 printf("%3d <<<", i);
4237 printf("%3d %5d phop=%2d %d.%d.%d.%d\n",
4238 sess->debugmap[i].hop,
4239 sess->debugmap[i].port,
4240 sess->debugmap[i].phop,
4241 (int)sess->debugmap[i].ip.S_un.S_un_b.s_b1,
4242 (int)sess->debugmap[i].ip.S_un.S_un_b.s_b2,
4243 (int)sess->debugmap[i].ip.S_un.S_un_b.s_b3,
4244 (int)sess->debugmap[i].ip.S_un.S_un_b.s_b4);
4245 }
4246 else
4247 {
4248 printf("%3d -->", i);
4249 printf("%3d %5d\n",
4250 sess->debugmap[i].hop,
4251 sess->debugmap[i].port);
4252 }
4253 }
4254 }*/
4255 if(sess->send_sock > 0)
4256 {
4257 #if defined(WIN32) || defined(_WIN32)
4258 closesocket(sess->send_sock);
4259 #else
4260 close(sess->send_sock);
4261 #endif
4262 sess->send_sock = 0;
4263 }
4264 #if defined(WIN32) || defined(_WIN32)
4265 if(sess->recv_sock > 0)
4266 {
4267 closesocket(sess->recv_sock);
4268 sess->recv_sock = 0;
4269 }
4270 #endif
4271 }
4272 /*---------------------------------------------------------------------------*/
setOutputStyle(int nstyle)4273 void setOutputStyle(int nstyle)
4274 {
4275 if(nstyle<0 || nstyle>2)
4276 global_output_style=0;
4277 else
4278 global_output_style=nstyle;
4279 }
4280
getOutputStyle(void)4281 int getOutputStyle(void)
4282 {
4283 return global_output_style;
4284 }
4285
outputStyleIsXML(void)4286 int outputStyleIsXML(void)
4287 {
4288 if(global_output_style==1)
4289 return 1;
4290 return 0;
4291 }
4292
outputStyleIsGraphViz(void)4293 int outputStyleIsGraphViz(void)
4294 {
4295 if(global_output_style==2)
4296 return 1;
4297 return 0;
4298 }
4299 /*---------------------------------------------------------------------------*/
4300 #define INCSIZE 500
addtostringbuf(char * buf,size_t * bufsz,const char * addstr)4301 static char * addtostringbuf(char * buf, size_t * bufsz, const char * addstr)
4302 {
4303 if(!buf || !(*bufsz))
4304 {
4305 buf=malloc(INCSIZE);
4306 *bufsz=INCSIZE;
4307 buf[0]=0;
4308 }
4309 if(strlen(buf)+strlen(addstr)+1>(*bufsz))
4310 {
4311 buf=realloc(buf, (*bufsz)+INCSIZE);
4312 *bufsz+=INCSIZE;
4313 }
4314 strncat(buf,addstr,(*bufsz) - strlen(buf) - 1);
4315 return buf;
4316 }
4317 /*---------------------------------------------------------------------------*/
addNodeToRouteMap(char * routemap,size_t * routemapsz,char * prevlevelnodes,char ** currlevelnodes,size_t * currlevelnodessz,char * node)4318 static char * addNodeToRouteMap(char * routemap, size_t * routemapsz, char * prevlevelnodes, char ** currlevelnodes, size_t * currlevelnodessz, char * node)
4319 {
4320 char * pnode, * pnodeend;
4321 char pathbuff[100];
4322 if((*currlevelnodes) && (*currlevelnodessz))
4323 *currlevelnodes=addtostringbuf(*currlevelnodes, currlevelnodessz, ";");
4324 *currlevelnodes=addtostringbuf(*currlevelnodes, currlevelnodessz, node);
4325 pnode=prevlevelnodes;
4326 pnodeend=pnode;
4327 while(pnodeend)
4328 {
4329 pnodeend=strchr(pnode,';');
4330 if(pnodeend)
4331 *pnodeend=0;
4332 snprintf(pathbuff,100,"\t%s -> %s;\n",pnode,node);
4333 routemap=addtostringbuf(routemap, routemapsz, pathbuff);
4334 if(pnodeend)
4335 {
4336 *pnodeend=';';
4337 pnode=pnodeend+1;
4338 }
4339 }
4340 return routemap;
4341 }
4342 /*---------------------------------------------------------------------------*/
UpdateLatency(const struct trace_packet_info_s * tp,double * minlat,double * maxlat,int * latinitialized)4343 static void UpdateLatency(const struct trace_packet_info_s *tp, double * minlat, double * maxlat, int * latinitialized)
4344 {
4345 double currlat=timediff_ms(tp->sent, tp->recv);
4346 if(!(*latinitialized))
4347 {
4348 *minlat=currlat;
4349 *maxlat=currlat;
4350 *latinitialized=1;
4351 }
4352 else
4353 {
4354 if(*minlat > currlat)
4355 *minlat=currlat;
4356 if(*maxlat < currlat)
4357 *maxlat=currlat;
4358 }
4359 }
4360 /*---------------------------------------------------------------------------*/
PrintPacketInfoForGraphViz(lft_session_params * sess,const struct trace_packet_info_s * tp)4361 static void PrintPacketInfoForGraphViz(lft_session_params * sess, const struct trace_packet_info_s *tp)
4362 {
4363 if(tp->recv.tv_sec)
4364 {
4365 if (tp->last_hop.s_addr != tp->hopaddr.s_addr)
4366 {
4367 if (sess->do_aslookup)
4368 {
4369 if (tp->asnumber)
4370 printf(" [%d]", tp->asnumber);
4371 else
4372 printf(" [AS?]");
4373 }
4374 if (sess->do_netlookup)
4375 {
4376 if((uintptr_t)tp->netname && strlen(tp->netname)>0)
4377 printf(" [%s]", tp->netname);
4378 else
4379 printf(" [Net?]");
4380 }
4381 if (tp->icmp_type < -2 || tp->icmp_type > 17)
4382 printf (" [icmp code %d]", tp->icmp_type);
4383 else
4384 {
4385 if (tp->icmp_type >= 0)
4386 printf (" [%s]", icmp_messages[tp->icmp_type + 1]);
4387 }
4388
4389 printf(" ");
4390 print_host (sess, tp->hopaddr);
4391 if (tp->icmp_type == -1 && (sess->protocol<2 || sess->protocol>3))
4392 printf(":%d",sess->dport);
4393 }
4394 }
4395 }
4396 /*---------------------------------------------------------------------------*/
GraphVizOutput(lft_session_params * sess)4397 void GraphVizOutput(lft_session_params * sess)
4398 {
4399 int reply,noreply,neglstart,neglend,anomtype,hopno,maxhop,icmpcode,holecount=0;
4400 char * rankstring=NULL;
4401 size_t rankstringsz=0;
4402 struct trace_packet_info_s *tp;
4403 char netnamecopy[512];
4404 char * prevlevelnodes=NULL;
4405 size_t prevlevelnodessz=0;
4406 char * currlevelnodes=NULL;
4407 size_t currlevelnodessz=0;
4408 char * routemap=NULL;
4409 size_t routemapsz;
4410 char nodenamebuff[200];
4411 double minlat, maxlat;
4412 char latencybuf[100];
4413 int latinitialized;
4414 int asseam_hopno=-1;
4415 struct in_addr asseam_hopaddr;
4416 int netseam_hopno=-1;
4417 struct in_addr netseam_hopaddr;
4418 struct in_addr classbmask;
4419 struct in_addr masked_target;
4420 int prevasn=-1;
4421 struct in_addr prevasn_hopaddr;
4422 int prevasn_hopno;
4423 int lastishole;
4424 int netreached=0;
4425 int isseam;
4426 char cpath[1024];
4427 int lastpos;
4428
4429 if(sess->is_graphviz_subquery)
4430 return;
4431
4432 if(sess->graphviz_icon_path)
4433 strncpy(cpath,sess->graphviz_icon_path,1022);
4434 else
4435 {
4436 if(!getcwd(cpath,1022))
4437 {
4438 cpath[0]='.';
4439 cpath[1]=DIRECTORY_SPLITTER;
4440 cpath[2]=0;
4441 }
4442 }
4443 lastpos=strlen(cpath)-1;
4444 if(cpath[lastpos]!=DIRECTORY_SPLITTER)
4445 {
4446 cpath[lastpos+1]=DIRECTORY_SPLITTER;
4447 cpath[lastpos+2]=0;
4448 }
4449
4450 inet_aton("255.255.0.0", &classbmask);
4451 masked_target.s_addr=sess->remote_address.s_addr & classbmask.s_addr;
4452
4453 printf("digraph %s {\n",GVGRAPHNAME);
4454 printf("\trankdir=TB;\n\tnode [fontname=%s,fontsize=%s];\n",GVFONTNAME,GVFONTSIZE);
4455 printf("\tSRC[%s, label=<",GVHOPSTYLE_SOURCE);
4456 prevlevelnodes=addtostringbuf(prevlevelnodes, &prevlevelnodessz, "SRC");
4457 rankstring=addtostringbuf(rankstring, &rankstringsz, "Source");
4458 printf("%s%s%s%s",GVNTBEG,cpath,GVNIMG_SOURCE,GVNTMID);
4459 print_host (sess, sess->local_address);
4460 if(sess->protocol==2 || sess->protocol==3)
4461 printf("%s>];\n",GVNTEND);
4462 else
4463 {
4464 if (sess->random_source)
4465 printf (":%d (pseudo-random)%s>];\n", sess->sport, GVNTEND);
4466 else
4467 printf (":%d%s>];\n", sess->sport, GVNTEND);
4468 }
4469 if (sess->num_hops)
4470 maxhop = sess->num_hops;
4471 else
4472 maxhop = sess->hop_info_length - 1;
4473 noreply = 0;
4474 reply = 0;
4475 neglstart=-1;
4476 neglend=-1;
4477 /* Find SEAMs at first*/
4478 for(hopno = sess->ttl_min; hopno < sess->hop_info_length; hopno++)
4479 {
4480 icmpcode=-100;
4481 if(sess->hop_info[hopno].all_rcvd)
4482 {
4483 lastishole=0;
4484 SLIST_FOREACH(tp, &(sess->hop_info[hopno].packets), next_by_hop)
4485 {
4486 if(tp->recv.tv_sec)
4487 {
4488 if(hopno<=maxhop)
4489 icmpcode=tp->icmp_type;
4490 if(tp->last_hop.s_addr != tp->hopaddr.s_addr)
4491 {
4492 if((tp->hopaddr.s_addr & classbmask.s_addr) == masked_target.s_addr)
4493 netreached=1;
4494 else
4495 {
4496 netseam_hopno=hopno;
4497 netseam_hopaddr=tp->hopaddr;
4498 }
4499 if(sess->do_aslookup || sess->do_netlookup)
4500 {
4501 if(prevasn==-1)
4502 {
4503 if(tp->asnumber)
4504 {
4505 prevasn=tp->asnumber;
4506 prevasn_hopno=hopno;
4507 prevasn_hopaddr=tp->hopaddr;
4508 }
4509 }
4510 else
4511 {
4512 if(tp->asnumber)
4513 {
4514 if(tp->asnumber!=prevasn)
4515 {
4516 asseam_hopno=prevasn_hopno;
4517 asseam_hopaddr=prevasn_hopaddr;
4518 }
4519 prevasn=tp->asnumber;
4520 prevasn_hopno=hopno;
4521 prevasn_hopaddr=tp->hopaddr;
4522 }
4523 }
4524 }
4525 }
4526 }
4527 }
4528 }
4529 else
4530 lastishole=1;
4531 if(icmpcode==-1)
4532 break;
4533 }
4534 if(!netreached)
4535 netseam_hopno=-1;
4536 if(lastishole)
4537 asseam_hopno=-1;
4538 for(hopno = sess->ttl_min; hopno < sess->hop_info_length; hopno++)
4539 {
4540 icmpcode=-100;
4541 latinitialized=0;
4542 anomtype=0;
4543 if((sess->hop_info[hopno].state == HS_SEND_FIN) && (sess->hop_info[hopno+1].state == HS_SEND_SYN) && (sess->hop_info[hopno+1].ts_last_recv.tv_sec))
4544 anomtype=1;
4545 if((sess->hop_info[hopno].state != HS_SEND_SYN_ACK) && (sess->hop_info[hopno+1].state == HS_SEND_SYN_ACK) && (hopno == (sess->num_hops - 1)))
4546 anomtype=2;
4547 if((sess->hop_info[hopno].flags & HF_ENDPOINT) && (noreply >= ((maxhop - sess->ttl_min)/2)) && sess->num_hops > 3)
4548 anomtype=3;
4549 if(sess->hop_info[hopno].all_rcvd == 0)
4550 {
4551 reply=0;
4552 if(neglstart==-1)
4553 neglstart=hopno;
4554 neglend=hopno;
4555 }
4556 else
4557 {
4558 if(neglstart!=-1)
4559 {
4560 holecount++;
4561 printf("\tHOLE%d[%s, label=<",holecount,GVHOPSTYLE_HOLE);
4562 printf("%s%s%s%s",GVNTBEG,cpath,GVNIMG_HOLE,GVNTMID);
4563 snprintf(nodenamebuff,200,"HOLE%d",holecount);
4564 printf("Potentially Cloaked Device%s>];\n",GVNTEND);
4565 routemap=addNodeToRouteMap(routemap, &routemapsz, prevlevelnodes, &currlevelnodes, &currlevelnodessz, nodenamebuff);
4566 free(prevlevelnodes);
4567 prevlevelnodes=currlevelnodes;
4568 prevlevelnodessz=currlevelnodessz;
4569 currlevelnodes=NULL;
4570 currlevelnodessz=0;
4571 if(neglstart == neglend)
4572 snprintf(nodenamebuff,200,"\"No reply received from TTL %d\"", neglstart+1);
4573 else
4574 snprintf(nodenamebuff,200,"\"No reply received from TTLs %d through %d\"", neglstart+1, neglend+1);
4575 rankstring=addtostringbuf(rankstring, &rankstringsz, " -> ");
4576 rankstring=addtostringbuf(rankstring, &rankstringsz, nodenamebuff);
4577 neglstart=-1;
4578 neglend=-1;
4579 }
4580 int cnt=0;
4581 SLIST_FOREACH(tp, &(sess->hop_info[hopno].packets), next_by_hop)
4582 {
4583 if(tp->recv.tv_sec)
4584 {
4585 const char * img=GVNIMG_REGULAR;
4586 cnt++;
4587 if(hopno<=maxhop)
4588 icmpcode=tp->icmp_type;
4589 reply = 1;
4590 strncpy(netnamecopy, tp->netname, 511);
4591 if(tp->last_hop.s_addr != tp->hopaddr.s_addr)
4592 {
4593 if(icmpcode==-1)
4594 {
4595 printf("\tTRG[");
4596 snprintf(nodenamebuff,200,"TRG");
4597
4598 if(sess->target_open > 0)
4599 {
4600 printf("%s, label=<%s%s", GVHOPSTYLE_TARGET_OPEN,GVNTBEG,cpath);
4601 img=GVNIMG_TRGOPEN;
4602 }
4603 else
4604 {
4605 if(sess->target_filtered)
4606 {
4607 printf("%s, label=<%s%s", GVHOPSTYLE_TARGET_FILTERED,GVNTBEG,cpath);
4608 img=GVNIMG_TRGFILTERED;
4609 }
4610 else
4611 {
4612 printf("%s, label=<%s%s", GVHOPSTYLE_TARGET_CLOSED, GVNTBEG, cpath);
4613 img=GVNIMG_TRGCLOSED;
4614 }
4615 }
4616 }
4617 else
4618 {
4619 printf("\tHOP%d_%d[",hopno+1,cnt);
4620 snprintf(nodenamebuff,200,"HOP%d_%d",hopno+1,cnt);
4621 switch (anomtype)
4622 {
4623 case 1:
4624 printf("%s, label=<%s%s", GVHOPSTYLE_ANOMALY1, GVNTBEG, cpath);
4625 img=GVNIMG_ANOMALY1;
4626 break;
4627 case 2:
4628 printf("%s, label=<%s%s", GVHOPSTYLE_ANOMALY2, GVNTBEG, cpath);
4629 img=GVNIMG_ANOMALY2;
4630 break;
4631 case 3:
4632 printf("%s, label=<%s%s", GVHOPSTYLE_ANOMALY3, GVNTBEG, cpath);
4633 img=GVNIMG_ANOMALY3;
4634 break;
4635 default:
4636 printf("%s, label=<%s%s", GVHOPSTYLE_BASE, GVNTBEG, cpath);
4637 img=GVNIMG_REGULAR;
4638 break;
4639 }
4640 }
4641 if(img==GVNIMG_REGULAR && ((hopno==asseam_hopno && tp->hopaddr.s_addr==asseam_hopaddr.s_addr) || (hopno==netseam_hopno && tp->hopaddr.s_addr==netseam_hopaddr.s_addr)))
4642 img=GVNIMG_SEAM;
4643 routemap=addNodeToRouteMap(routemap, &routemapsz, prevlevelnodes, &currlevelnodes, &currlevelnodessz, nodenamebuff);
4644 UpdateLatency(tp,&minlat,&maxlat,&latinitialized);
4645 printf("%s%s",img,GVNTMID);
4646 PrintPacketInfoForGraphViz(sess,tp);
4647 isseam=0;
4648 if(hopno==asseam_hopno && tp->hopaddr.s_addr==asseam_hopaddr.s_addr)
4649 {
4650 printf("</td></tr><tr><td>(AS-Method Seam");
4651 isseam=1;
4652 }
4653 if(hopno==netseam_hopno && tp->hopaddr.s_addr==netseam_hopaddr.s_addr)
4654 {
4655 printf("</td></tr><tr><td>(Network-Method Seam");
4656 isseam=1;
4657 }
4658 if(isseam)
4659 {
4660 if(sess->check_seam)
4661 {
4662 printf(": ");
4663 char hostname[100];
4664 lft_session_params * subsess=LFTSessionOpen();
4665 strncpy(hostname, inet_ntoa(tp->hopaddr),100);
4666 subsess->senddevsel = 1;
4667 subsess->senddev = sess->pcap_send_dev;
4668 subsess->userdevsel = 1;
4669 subsess->userdev = sess->pcap_dev;
4670 subsess->auto_ports=0;
4671 subsess->dport=179;
4672 subsess->seq_start=30;
4673 subsess->retry_min=1;
4674 subsess->retry_max=1;
4675 subsess->resolve_names=0;
4676 subsess->ahead_limit=1;
4677 subsess->break_on_icmp = 0;
4678 subsess->is_graphviz_subquery=1;
4679 subsess->hostname=hostname;
4680 subsess->hostname_lsrr_size = 0;
4681 LFTExecute(subsess);
4682 if(subsess->target_open > 0)
4683 printf("Vulnerable/Handshake");
4684 else
4685 {
4686 if(subsess->target_filtered)
4687 printf("Protected/Filtered");
4688 else
4689 printf("Vulnerable/Shun");
4690 }
4691 LFTSessionClose(subsess);
4692 }
4693 printf(")");
4694 }
4695 printf("%s>];\n",GVNTEND);
4696 }
4697 else
4698 UpdateLatency(tp,&minlat,&maxlat,&latinitialized);
4699 }
4700 }
4701 if(minlat==maxlat)
4702 snprintf(latencybuf,100,": %.1fms",minlat);
4703 else
4704 snprintf(latencybuf,100,": %.1f - %.1fms",minlat,maxlat);
4705 if(icmpcode==-1)
4706 {
4707 rankstring=addtostringbuf(rankstring, &rankstringsz, " -> \"Destination");
4708 if (sess->protocol==0 || sess->protocol==4)
4709 {
4710 rankstring=addtostringbuf(rankstring, &rankstringsz, " [target ");
4711 if (sess->target_open > 0)
4712 rankstring=addtostringbuf(rankstring, &rankstringsz, "open]");
4713 else
4714 {
4715 if(sess->target_filtered > 0)
4716 rankstring=addtostringbuf(rankstring, &rankstringsz, "filtered]");
4717 else
4718 rankstring=addtostringbuf(rankstring, &rankstringsz, "closed]");
4719 }
4720 }
4721 rankstring=addtostringbuf(rankstring, &rankstringsz, latencybuf);
4722 }
4723 else
4724 {
4725 snprintf(nodenamebuff,200,"\"%d", hopno+1);
4726 rankstring=addtostringbuf(rankstring, &rankstringsz, " -> ");
4727 rankstring=addtostringbuf(rankstring, &rankstringsz, nodenamebuff);
4728 rankstring=addtostringbuf(rankstring, &rankstringsz, latencybuf);
4729 }
4730 switch (anomtype)
4731 {
4732 case 1:
4733 rankstring=addtostringbuf(rankstring, &rankstringsz, "\\n");
4734 rankstring=addtostringbuf(rankstring, &rankstringsz, GV_ANOMALY1_TEXT);
4735 break;
4736 case 2:
4737 rankstring=addtostringbuf(rankstring, &rankstringsz, "\\n");
4738 rankstring=addtostringbuf(rankstring, &rankstringsz, GV_ANOMALY2_TEXT);
4739 break;
4740 case 3:
4741 rankstring=addtostringbuf(rankstring, &rankstringsz, "\\n");
4742 rankstring=addtostringbuf(rankstring, &rankstringsz, GV_ANOMALY3_TEXT);
4743 break;
4744 default:
4745 break;
4746 }
4747 rankstring=addtostringbuf(rankstring, &rankstringsz, "\"");
4748
4749 free(prevlevelnodes);
4750 prevlevelnodes=currlevelnodes;
4751 prevlevelnodessz=currlevelnodessz;
4752 currlevelnodes=NULL;
4753 currlevelnodessz=0;
4754 }
4755 if(icmpcode==-1)
4756 break;
4757 }
4758 if(neglstart!=-1)
4759 {
4760 holecount++;
4761 printf("\tHOLE%d[%s, label=<",holecount,GVHOPSTYLE_HOLE);
4762 printf("%s%s%s%s",GVNTBEG,cpath,GVNIMG_HOLE,GVNTMID);
4763 snprintf(nodenamebuff,200,"HOLE%d",holecount);
4764 printf("No Response%s>];\n",GVNTEND);
4765 routemap=addNodeToRouteMap(routemap, &routemapsz, prevlevelnodes, &currlevelnodes, &currlevelnodessz, nodenamebuff);
4766 free(prevlevelnodes);
4767 prevlevelnodes=currlevelnodes;
4768 prevlevelnodessz=currlevelnodessz;
4769 currlevelnodes=NULL;
4770 currlevelnodessz=0;
4771 snprintf(nodenamebuff,200,"\"No reply received after TTL %d\"", neglstart+1);
4772 rankstring=addtostringbuf(rankstring, &rankstringsz, " -> ");
4773 rankstring=addtostringbuf(rankstring, &rankstringsz, nodenamebuff);
4774 neglstart=-1;
4775 neglend=-1;
4776 }
4777 free(prevlevelnodes);
4778 printf("\tranksep=equally;\n\t{\n\t\tnode [shape=plaintext];\n\t\t%s;\n\t}\n",rankstring);
4779 free(rankstring);
4780 printf("%s",routemap);
4781 free(routemap);
4782 printf("}\n");
4783 }
4784 /*---------------------------------------------------------------------------*/
4785