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