1 /*
2  * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3  *               2002, 2003, 2004
4  *	Ohio University.
5  *
6  * ---
7  *
8  * Starting with the release of tcptrace version 6 in 2001, tcptrace
9  * is licensed under the GNU General Public License (GPL).  We believe
10  * that, among the available licenses, the GPL will do the best job of
11  * allowing tcptrace to continue to be a valuable, freely-available
12  * and well-maintained tool for the networking community.
13  *
14  * Previous versions of tcptrace were released under a license that
15  * was much less restrictive with respect to how tcptrace could be
16  * used in commercial products.  Because of this, I am willing to
17  * consider alternate license arrangements as allowed in Section 10 of
18  * the GNU GPL.  Before I would consider licensing tcptrace under an
19  * alternate agreement with a particular individual or company,
20  * however, I would have to be convinced that such an alternative
21  * would be to the greater benefit of the networking community.
22  *
23  * ---
24  *
25  * This file is part of Tcptrace.
26  *
27  * Tcptrace was originally written and continues to be maintained by
28  * Shawn Ostermann with the help of a group of devoted students and
29  * users (see the file 'THANKS').  The work on tcptrace has been made
30  * possible over the years through the generous support of NASA GRC,
31  * the National Science Foundation, and Sun Microsystems.
32  *
33  * Tcptrace is free software; you can redistribute it and/or modify it
34  * under the terms of the GNU General Public License as published by
35  * the Free Software Foundation; either version 2 of the License, or
36  * (at your option) any later version.
37  *
38  * Tcptrace is distributed in the hope that it will be useful, but
39  * WITHOUT ANY WARRANTY; without even the implied warranty of
40  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41  * General Public License for more details.
42  *
43  * You should have received a copy of the GNU General Public License
44  * along with Tcptrace (in the file 'COPYING'); if not, write to the
45  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
46  * MA 02111-1307 USA
47  *
48  * Author:	Shawn Ostermann
49  * 		School of Electrical Engineering and Computer Science
50  * 		Ohio University
51  * 		Athens, OH
52  *		ostermann@cs.ohiou.edu
53  *		http://www.tcptrace.org/
54  */
55 
56 
57 /*
58  *
59  * The newest gcc (3.3) is much pickier about the unused variables that
60  * we define for Copyright and RCSid, so this will shut it up.
61  *
62  */
63 #ifdef __GNUC__
64 #define GCC_UNUSED __attribute__((unused))
65 #else
66 #define GCC_UNUSED
67 #endif
68 
69 static char const GCC_UNUSED rcsid_tcptrace[] =
70     "@(#)$Header$";
71 
72 
73 #include <stdio.h>
74 #include <string.h>
75 #include <strings.h>
76 #include <sys/types.h>
77 #include <unistd.h>
78 #include <time.h>
79 #include <sys/time.h>
80 #include <sys/socket.h>
81 #include <net/if.h>
82 #if __FreeBSD__ >= 2
83 #include <osreldate.h>
84 #if __FreeBSD_version >= 300000
85 #include <net/if_var.h>
86 #endif
87 #endif
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <arpa/inet.h>
91 #include <netinet/if_ether.h>
92 #include <netinet/ip.h>
93 #include <netinet/tcp.h>
94 #include <netinet/udp.h>
95 #include <netdb.h>
96 #include <ctype.h>
97 #include <signal.h>
98 #include <sys/stat.h>
99 #include <stdarg.h>
100 #include <stdlib.h>
101 #include <math.h>
102 
103 /* IPv6 support */
104 #include "ipv6.h"
105 
106 /* dynamic string support */
107 #include "dstring.h"
108 
109 /* memory allocation routines */
110 #include "pool.h"
111 
112 /* we want LONG LONG in some places */
113 #if SIZEOF_UNSIGNED_LONG_LONG_INT >= 8
114 #define HAVE_LONG_LONG
115 typedef unsigned long long int u_llong;
116 typedef long long int llong;
117 /* Thanks to MacOSX, they use %qu to print unsigned long long ints */
118 /* There is a test to see if we need to use %qu or %llu to print these variables */
119 /* The test is located in configure.in */
120 #ifdef USE_LLU
121 #define FS_ULL "llu" /* For most systems use llu */
122 #define FS_LL  "lld" /* For most systems use ll */
123 #else /* USE_LLU */
124 #define FS_ULL "qu"  /* MacOSX use qu */
125 #define FS_LL  "qd"  /* MacOSX use qd */
126 #endif /* USE_LLU */
127 
128 #else /* LONG LONG */
129 typedef unsigned long int u_llong;
130 typedef long int llong;
131 #define FS_ULL "lu" /* No long long unsigned, so  use lu */
132 #define FS_LL  "ld" /* No long long ints, so use ld */
133 #endif /* LONG LONG */
134 
135 /* plotter information */
136 typedef int PLOTTER;
137 #define NO_PLOTTER -1
138 #define NCOLORS 8
139 extern char *ColorNames[NCOLORS];
140 /* {"green", "red", "blue", "yellow", "purple", "orange", "magenta", "pink"}; */
141 typedef struct pl_line *PLINE;
142 
143 /* max number of letters in endpoint name */
144 /* (8 allows 26**8 different endpoints (209,000,000,000)
145     probably plenty for now!!!!!) */
146 #define MAX_HOSTLETTER_LEN 8
147 
148 
149 /* several places in the code NEED numbers of a specific size. */
150 /* since the definitions aren't standard across everything we're */
151 /* trying to support, the types are gathered up here */
152 /* specifically, we need:
153    tt_uint32	unsigned 32 bit
154    tt_uint16	unsigned 16 bit
155    tt_int32	signed 32 bit
156    tt_int16	signed 16 bit
157 */
158 /* first, do the 32 bit ones */
159 #if SIZEOF_UNSIGNED_LONG_INT == 4
160 typedef unsigned long tt_uint32;
161 typedef          long tt_int32;
162 #else
163 #if SIZEOF_UNSIGNED_INT == 4
164 typedef unsigned int tt_uint32;
165 typedef          int tt_int32;
166 #else
167 OOPS: Please insert an appropriate 32-bit unsigned type here!
168 OOPS: Please insert an appropriate 32-bit signed type here!
169 #endif /* SIZEOF_UNSIGNED_INT == 4 */
170 #endif /* SIZEOF_UNSIGNED_LONG_INT == 4 */
171 /* first, do the 16 bit ones */
172 #if SIZEOF_UNSIGNED_INT == 2
173 typedef unsigned int tt_uint16;
174 typedef          int tt_int16;
175 #else
176 #if SIZEOF_UNSIGNED_SHORT == 2
177 typedef unsigned short tt_uint16;
178 typedef          short tt_int16;
179 #else
180 OOPS: Please insert an appropriate 16-bit unsigned type here!
181 OOPS: Please insert an appropriate 16-bit signed type here!
182 #endif /* SIZEOF_UNSIGNED_INT == 4 */
183 #endif /* SIZEOF_UNSIGNED_LONG_INT == 4 */
184 
185 
186 
187 /* type for a TCP sequence number, ACK, FIN, or SYN */
188 /* This type MUST be a 32-bit unsigned number */
189 typedef tt_uint32 seqnum;
190 
191 /* length of a segment */
192 typedef u_long seglen;
193 
194 /* type for a quadrant number */
195 typedef u_char quadnum;  /* 1,2,3,4 */
196 
197 /* type for a TCP port number */
198 typedef u_short portnum;
199 
200 /* type for an IP address */
201 /* IP address can be either IPv4 or IPv6 */
202 typedef struct ipaddr {
203     u_char addr_vers;	/* 4 or 6 */
204     union {
205 	struct in_addr   ip4;
206 	struct in6_addr  ip6;
207     } un;
208 } ipaddr;
209 
210 #ifndef __VMS
211 
212 /* some machines (TRUE64 for one) handle the 4-bit TCP/IP fields
213    differently, so this macro simplifies life */
214 #define IP_HL(pip)   ((pip)->ip_hl)
215 #define IP_V(pip)    ((pip)->ip_v)
216 #define TH_X2(ptcp)  ((ptcp)->th_x2)
217 #define TH_OFF(ptcp) ((ptcp)->th_off)
218 /* some systems (darwin at least) use this for something else */
219 
220 #else
221 
222 /* One alternative looks like this: */
223 #define IP_HL(pip)   ((pip)->ip_vhl&0xf)
224 #define IP_V(pip)    ((pip)->ip_vhl>>4)
225 #define TH_X2(ptcp)  ((ptcp)->th_xoff&0xf)
226 #define TH_OFF(ptcp) ((ptcp)->th_xoff>>4)
227 
228 #endif
229 
230 #undef TH_FLAGS
231 #define TH_FLAGS(ptcp) ((ptcp)->th_flags)
232 
233 /* type for a timestamp */
234 typedef struct timeval timeval;
235 #define ZERO_TIME(ptv)(((ptv)->tv_sec == 0) && ((ptv)->tv_usec == 0))
236 
237 
238 /* type for a Boolean */
239 typedef u_char Bool;
240 #define TRUE	1
241 #define FALSE	0
242 #define BOOL2STR(b) (b)?"TRUE":"FALSE"
243 
244 /* ACK types */
245 enum t_ack {NORMAL = 1,		/* no retransmits, just advance */
246 	    AMBIG = 2,		/* segment ACKed was rexmitted */
247 	    CUMUL = 3,		/* doesn't advance */
248 	    TRIPLE = 4,		/* triple dupack */
249 	    NOSAMP = 5};	/* covers retransmitted segs, no rtt sample */
250 
251 /* type for an internal file pointer */
252 typedef struct mfile MFILE;
253 
254 /* file name information */
255 extern char **filenames;	/* all the files on the cmd line */
256 extern char *cur_filename;	/* the current file */
257 
258 /* first and last packet timestamp */
259 extern timeval first_packet;
260 extern timeval last_packet;
261 
262 /* counters */
263 extern u_long tcp_trace_count;
264 extern u_long udp_trace_count;
265 
266 typedef struct segment {
267     seqnum	seq_firstbyte;	/* seqnumber of first byte */
268     seqnum 	seq_lastbyte;	/* seqnumber of last byte */
269     u_char	retrans;	/* retransmit count */
270     u_int	acked;		/* how MANY times has has it been acked? */
271     timeval	time;		/* time the segment was sent */
272     struct segment *next;
273     struct segment *prev;
274 } segment;
275 
276 typedef struct quadrant {
277     segment	*seglist_head;
278     segment	*seglist_tail;
279     Bool 	full;
280     struct quadrant *prev;
281     struct quadrant *next;
282 } quadrant;
283 
284 typedef struct seqspace {
285     quadrant 	*pquad[4];
286 } seqspace;
287 
288 typedef struct tcb {
289     /* parent pointer */
290     struct stcp_pair *ptp;
291     struct tcb	*ptwin;
292 
293     /* TCP information */
294     seqnum	ack;
295     seqnum	seq;
296     seqnum	syn;
297     seqnum	fin;
298     seqnum	windowend;
299     timeval	time;
300 
301     /* TCP options */
302     u_int	mss;
303     Bool	f1323_ws;	/* did he request 1323 window scaling? */
304     Bool	f1323_ts;	/* did he request 1323 timestamps? */
305     Bool	fsack_req;	/* did he request SACKs? */
306     u_char	window_scale;
307 
308 	/* If we are using window scaling, have we adjusted the
309 	   win_min field from the non-scaled window size
310 	   that appeared in the SYN packet?? */
311     Bool window_stats_updated_for_scaling;
312     u_llong     win_scaled_pkts; /* Used to calculate avg win adv */
313 
314     /* statistics added */
315     u_llong	data_bytes;
316     u_llong	data_pkts;
317     u_llong	data_pkts_push;
318     u_llong	unique_bytes;	/* bytes sent (-FIN/SYN), excluding rexmits */
319     u_llong	rexmit_bytes;
320     u_llong	rexmit_pkts;
321     u_llong	ack_pkts;
322     u_llong	pureack_pkts;	/* mallman - pure acks, no data */
323     u_long	win_max;
324     u_long	win_min;
325     u_llong	win_tot;
326     u_long      win_last;  /* last advertised window size*/
327     u_long	win_zero_ct;
328     u_llong	packets;
329     u_char	syn_count;
330     u_char	fin_count;
331     u_char	reset_count;  /* resets SENT */
332     u_long	min_seg_size;
333     u_long	max_seg_size;
334     u_llong	out_order_pkts;	/* out of order packets */
335     u_llong	sacks_sent;	/* sacks returned */
336     u_long	ipv6_segments;	/* how many segments were ipv6? */
337 
338 
339     /* stats on urgent data */
340     u_long     urg_data_bytes;
341     u_long     urg_data_pkts;
342 
343    /* Statistics to store the number of Zero window probes
344       seen and the total number of bytes spent for it. */
345     u_long      num_zwnd_probes;
346     u_long      zwnd_probe_bytes;
347 
348     /* stats on sequence numbers */
349 
350     seqnum	min_seq;	/* smallest seq number seen */
351     seqnum	max_seq;	/* largest seq number seen */
352     seqnum	latest_seq;	/* most recent seq number seen */
353 
354     /* stats on sequence space wrap arounds */
355     u_int quad1, quad2, quad3, quad4;  /* was every quadrant visited */
356     u_int seq_wrap_count;              /* wrap count */
357 
358     /* hardware duplicate detection */
359 #define SEGS_TO_REMEMBER 8
360     struct str_hardware_dups {
361 	seqnum	hwdup_seq;	/* sequence number */
362 	u_short	hwdup_id;	/* IP ID */
363 	u_long	hwdup_packnum; /* packet number */
364     } hardware_dups[SEGS_TO_REMEMBER];
365     u_long num_hardware_dups;
366     u_char hardware_dups_ix;
367 
368     /* did I detect any "bad" tcp behavior? */
369     /* at present, this means: */
370     /*  - SYNs retransmitted with different sequence numbers */
371     /*  - FINs retransmitted with different sequence numbers */
372     Bool	bad_behavior;
373 
374     /* added for initial window stats (for Mallman) */
375     u_long	initialwin_bytes;	/* initial window (in bytes) */
376     u_long	initialwin_segs;	/* initial window (in segments) */
377     Bool	data_acked;	/* has any non-SYN data been acked? */
378 
379     /* added for (estimated) congestions window stats (for Mallman) */
380     u_long	owin_max;
381     u_long	owin_min;
382     u_llong	owin_tot;
383     u_llong	owin_wavg;  /* weighted owin */
384     u_llong     owin_count;
385     u_long	previous_owin_sample;
386     timeval     previous_owin_sample_time;
387 
388     /* RTT stats for singly-transmitted segments */
389     double	rtt_last;	/* RTT as of last good ACK (microseconds) */
390     u_long	rtt_min;
391     u_long	rtt_max;
392     double	rtt_sum;	/* for averages */
393     double	rtt_sum2;	/* sum of squares, for stdev */
394     u_long	rtt_count;	/* for averages */
395     /* RTT stats for multiply-transmitted segments */
396     u_long	rtt_min_last;
397     u_long	rtt_max_last;
398     double	rtt_sum_last;	/* from last transmission, for averages */
399     double	rtt_sum2_last;	/* sum of squares, for stdev */
400     u_long	rtt_count_last;	/* from last transmission, for averages */
401 
402 	/* To keep track of stats for FULL SIZE segments
403 	   Simple heuristic :
404 	   We shall treat the largest packet, so far seen as the
405 	   "full size" packet and collect stats. accordingly.
406 	   Upon seeing a bigger packet, we flush all stats. collected
407 	   incorrectly and begin all over again */
408 	u_long rtt_full_size;
409 
410 	u_long rtt_full_min;
411 	u_long rtt_full_max;
412 	double rtt_full_sum;	/* for averages */
413 	double rtt_full_sum2;	/* sum of squares for stdev */
414 	u_long rtt_full_count;	/* for averages */
415 
416 	u_long rtt_3WHS;		/* rtt value used to seed RTO timers */
417 
418     /* ACK Counters */
419     u_llong	rtt_amback;	/* ambiguous ACK */
420     u_llong	rtt_cumack;	/* segments only cumulativly ACKed */
421     u_llong	rtt_nosample;	/* segments ACKED, but after retransmission */
422 				/* of earlier segments, so sample isn't */
423 				/* valid */
424     u_llong	rtt_unkack;	/* unknown ACKs  ??? */
425     u_llong	rtt_dupack;	/* duplicate ACKs */
426     u_llong	rtt_triple_dupack; /* triple duplicate ACKs */
427     /* retransmission information */
428     seqspace    *ss;		/* the sequence space*/
429     u_long	retr_max;	/* maximum retransmissions ct */
430     u_long	retr_min_tm;	/* minimum retransmissions time */
431     u_long	retr_max_tm;	/* maximum retransmissions time */
432     double	retr_tm_sum;	/* for averages */
433     double	retr_tm_sum2;	/* sum of squares, for stdev */
434     u_long	retr_tm_count;	/* for averages */
435 
436     /* Instantaneous throughput info */
437     timeval	thru_firsttime;	/* time of first packet this interval */
438     u_long	thru_bytes;	/* number of bytes this interval */
439     u_long	thru_pkts;	/* number of packets this interval */
440     PLOTTER	thru_plotter;	/* throughput data dump file */
441     timeval	thru_lasttime;	/* time of previous segment */
442     PLINE	thru_avg_line;	/* average throughput line */
443     PLINE	thru_inst_line;	/* instantaneous throughput line */
444 
445     /* data transfer time stamps - mallman */
446     timeval	first_data_time;
447     timeval	last_data_time;
448 
449     /* Time Sequence Graph info for this one */
450     PLOTTER	tsg_plotter;
451     char	*tsg_plotfile;
452 
453     /* Time Line Graph */
454     PLOTTER     tline_plotter;
455 
456     /* Dumped RTT samples */
457     MFILE	*rtt_dump_file;
458 
459     /* Extracted stream contents */
460     MFILE	*extr_contents_file;
461     u_llong	trunc_bytes;	/* data bytes not see due to trace file truncation */
462     u_llong	trunc_segs;	/* segments with trunc'd bytes */
463     seqnum	extr_lastseq;	/* last sequence number we stored */
464     seqnum	extr_initseq;	/* initial sequence number (same as SYN unless we missed it) */
465 
466     /* RTT Graph info for this one */
467     PLOTTER	rtt_plotter;
468     PLINE	rtt_line;
469 
470     /* Segment size graph */
471     PLOTTER	segsize_plotter;
472     PLINE	segsize_line;
473     PLINE	segsize_avg_line;
474 
475     /* Congestion window graph */
476     PLOTTER	owin_plotter;
477     PLINE	owin_line;
478     PLINE       rwin_line;
479     PLINE	owin_avg_line;
480     PLINE 	owin_wavg_line;
481 
482     /* RWIN Graph info for this one */
483     PLOTTER	recvwin_plotter;
484     PLINE	recvwin_line;
485 
486     /* for tracking unidirectional idle time */
487     timeval	last_time;	/* last packet SENT from this side */
488     u_llong	idle_max;	/* maximum idle time observed (usecs) */
489 
490     /* for looking for interesting SACK blocks */
491     u_long	num_sacks;
492     u_long	max_sack_blocks;
493     u_long	num_dsacks;
494 
495     /* for computing LEAST (see FAQ) */
496     enum	tcp_strains { TCP_RENO, TCP_SACK, TCP_DSACK } tcp_strain;
497     u_long	LEAST;
498     char	in_rto;
499     u_long	recovered, recovered_orig, rto_segment, lastackno;
500     u_long	event_retrans, event_dupacks;
501 
502     /* host name letter(s) */
503     char	*host_letter;
504 } tcb;
505 
506 
507 typedef u_short hash;
508 
509 typedef struct {
510     ipaddr	a_address;
511     ipaddr	b_address;
512     portnum	a_port;
513     portnum	b_port;
514     hash	hash;
515 } tcp_pair_addrblock;
516 
517 
518 struct stcp_pair {
519     /* are we ignoring this one?? */
520     Bool		ignore_pair;
521 
522     /* inactive (previous instance of current connection */
523     Bool		inactive;
524 
525     /* endpoint identification */
526     tcp_pair_addrblock	addr_pair;
527 
528     /* connection naming information */
529     char		*a_hostname;
530     char		*b_hostname;
531     char		*a_portname;
532     char		*b_portname;
533     char		*a_endpoint;
534     char		*b_endpoint;
535 
536     /* connection information */
537     timeval		first_time;
538     timeval		last_time;
539     u_llong		packets;
540     tcb			a2b;
541     tcb			b2a;
542 
543 
544     /* module-specific structures, if requested */
545     void		**pmod_info;
546 
547     /* which file this connection is from */
548     char		*filename;
549 };
550 typedef struct stcp_pair tcp_pair;
551 
552 typedef struct tcphdr tcphdr;
553 
554 
555 extern int num_tcp_pairs;	/* how many pairs are in use */
556 extern tcp_pair **ttp;		/* array of pointers to allocated pairs */
557 
558 /* Wed Aug 20, 2003 - Ramani*/
559 /*  Prior to version 6.4.11, the data structure for storing the snapshots of
560  connections was a hashtable with linked lists. But this might lead to a
561  worst case scenario when many connections hash to the same hash table entry.
562  In such a case, searching for the connections degrades to searching a linked
563  list with a worst case complexity of O(number of connections in list). Hence
564  the new version implements an AVL tree in place of linked list leading to a
565  worst case complexity of O(ln(number of connections in tree)).
566     The modified data structure was tested with dumpfiles containing lots of
567  connections. A comparison of the profiles suggests an improvement in the time
568  spent in the dotrace function. Even though the AVL tree implementation
569  involves balancing the tree, since most of the accesses involve searching the
570  data structure, AVL tree performs MUCH better than linked list.
571      The algorithms for AVL tree implementation are based on those explained in
572  "Data Structures and Program Design in C by Robert L.Kruse, Bruce P.Leung,
573  Clovis L.Tondo". The source code for AVL tree implementation is from the
574  Institute of Applied Iconoclasm who put up the source code at
575  <http://www.purists.org>. We thank Georg for the source code whose mail
576  address has been mentioned as <georg@purists.org> */
577 
578 /* Data structures for AVL tree */
579 
580 /* Which of a given node's subtrees is higher in the AVL tree */
581 enum AVLSKEW {
582    EQUAL1, LEFT, RIGHT
583 };
584 
585 /* Did an insertion/deletion succeed and if we need to balance the AVL tree */
586 enum AVLRES {
587    OK, BALANCE
588 };
589 
590 /* Tue Nov 17, 1998 */
591 /* prior to version 5.13, we kept a hash table of all of the connections. */
592 /* The most recently-accessed connections move to the front of the bucket */
593 /* linked list.  Unfortunately, when reading thousands of connections on */
594 /* a machine with limited physical memory, this worked poorly.  Every time */
595 /* a new connection opened, we had to search the entire bucket, which */
596 /* pulled all of the paged-out connections back into memory.  The new */
597 /* system keeps a quick snapshot of the connection (ptp_snap) in the */
598 /* hash table.  We only retrieve the connection record if the snapshot */
599 /* matches. The result is that it works MUCH better when memory is low. */
600 typedef struct ptp_snap {
601     enum AVLSKEW        skew;      /* Skew of the AVL tree node */
602     tcp_pair_addrblock	addr_pair; /* just a copy */
603     struct ptp_snap     *left, *right;  /* Left and right trees of the AVL node */
604     void		*ptp;
605 } ptp_snap;
606 
607 
608 typedef struct ptp_ptr {
609   struct ptp_ptr	*next;
610   struct ptp_ptr	*prev;
611   struct ptp_snap	*from;
612   tcp_pair		*ptp;
613 } ptp_ptr;
614 
615 #define NONREAL_LIVE_CONN_INTERVAL      4*60    /* 4 minutes */
616 #define REMOVE_LIVE_CONN_INTERVAL	8*3600	/* 8 hours */
617 #define REMOVE_CLOSED_CONN_INTERVAL	8*60	/* 8 minutes */
618 #define UPDATE_INTERVAL			30	/* 30 seconds */
619 #define MAX_CONN_NUM			50000	/* max number of connections */
620 						/* for continuous mode */
621 
622 /* minimal support for UDP "connections" */
623 typedef struct ucb {
624     /* parent pointer */
625     struct sudp_pair *pup;
626     struct ucb	*ptwin;
627 
628     /* statistics added */
629     u_llong	data_bytes;
630     u_llong	packets;
631     u_long	min_dg_size;
632     u_long	max_dg_size;
633 
634     /* host name letter(s) */
635     char	*host_letter;
636 } ucb;
637 
638 
639 
640 typedef tcp_pair_addrblock udp_pair_addrblock;
641 struct sudp_pair {
642     /* Are we ignoring this 'connection' ? */
643     Bool                ignore_pair;
644 
645     /* endpoint identification */
646     udp_pair_addrblock	addr_pair;
647 
648     /* connection naming information */
649     char		*a_hostname;
650     char		*b_hostname;
651     char		*a_portname;
652     char		*b_portname;
653     char		*a_endpoint;
654     char		*b_endpoint;
655 
656     /* connection information */
657     timeval		first_time;
658     timeval		last_time;
659     u_llong		packets;
660     ucb			a2b;
661     ucb			b2a;
662 
663     /* module-specific structures, if requested */
664     void		**pmod_info;
665 
666     /* which file this connection is from */
667     char		*filename;
668 
669     /* linked list of usage */
670     struct sudp_pair *next;
671 };
672 typedef struct sudp_pair udp_pair;
673 typedef struct udphdr udphdr;
674 
675 
676 extern int num_udp_pairs;	/* how many pairs are in use */
677 extern udp_pair **utp;		/* array of pointers to allocated pairs */
678 
679 
680 /* option flags */
681 extern Bool colorplot;
682 extern Bool dump_rtt;
683 extern Bool graph_rtt;
684 extern Bool graph_tput;
685 extern Bool graph_tsg;
686 extern Bool graph_segsize;
687 extern Bool graph_owin;
688 extern Bool graph_tline;
689 extern Bool graph_recvwin;
690 extern Bool hex;
691 extern Bool ignore_non_comp;
692 extern Bool resolve_ipaddresses;
693 extern Bool resolve_ports;
694 extern Bool triple_dupack_allows_data;
695 extern Bool verify_checksums;
696 extern Bool print_rtt;
697 extern Bool print_owin;
698 extern Bool printbrief;
699 extern Bool printsuppress;
700 extern Bool printem;
701 extern Bool printallofem;
702 extern Bool printticks;
703 extern Bool dump_packet_data;
704 extern Bool warn_ooo;
705 extern Bool warn_printtrunc;
706 extern Bool warn_printbadmbz;
707 extern Bool warn_printhwdups;
708 extern Bool warn_printbad_syn_fin_seq;
709 extern Bool show_out_order;
710 extern Bool show_rexmit;
711 extern Bool show_zero_window;
712 extern Bool show_urg;
713 extern Bool show_sacks;
714 extern Bool show_rtt_dongles;
715 extern Bool show_triple_dupack;
716 extern Bool show_zwnd_probes;
717 extern Bool use_short_names;
718 extern Bool save_tcp_data;
719 extern Bool graph_time_zero;
720 extern Bool graph_seq_zero;
721 extern Bool print_seq_zero;
722 extern Bool graph_zero_len_pkts;
723 extern Bool plot_tput_instant;
724 extern Bool filter_output;
725 extern Bool do_udp;
726 extern Bool show_title;
727 extern Bool show_rwinline;
728 extern Bool docheck_hw_dups;
729 /* constants for real-time (continuous) mode */
730 extern Bool run_continuously;
731 extern Bool conn_num_threshold;
732 extern Bool xplot_all_files;
733 extern Bool ns_hdrs;
734 extern Bool dup_ack_handling;
735 extern Bool csv;
736 extern Bool tsv;
737 extern u_long remove_live_conn_interval;
738 extern u_long nonreal_live_conn_interval;
739 extern u_long remove_closed_conn_interval;
740 extern u_long update_interval;
741 extern u_long max_conn_num;
742 
743 extern int debug;
744 extern int thru_interval;
745 extern u_long pnum;
746 
747 /* extended variables with values */
748 extern char *output_file_dir;
749 extern char *output_file_prefix;
750 extern char *xplot_title_prefix;
751 extern char *xplot_args;
752 extern char *sv;
753 extern char *sp;       /* Separator used for long output with <SP>-separated-values */
754 
755 /* Used to comment out header lines of the long output
756  * when <SP>-separated-values is requested
757  */
758 extern char *comment;
759 
760 extern u_long ctrunc;
761 extern timeval current_time;
762 extern char *output_filename;
763 
764 /* first and last packet timestamp */
765 extern timeval first_packet;
766 extern timeval last_packet;
767 
768 
769 #define MAX_NAME 20
770 
771 
772 
773 /* external routine decls */
774 double sqrt(double x);
775 void free(void *);
776 int finite(double);
777 
778 /* note that many machines have an ether_ntoa, but the output differs, as does
779    the prototype, so we'll include our own and change the name to avoid conflicts
780    with local prototypes if they exist and differ */
781 char *Ether_Ntoa(struct ether_addr *e);
782 
783 /* global routine decls */
784 void *MallocZ(int);
785 void *ReallocZ(void *oldptr, int obytes, int nbytes);
786 void trace_init(void);
787 void trace_done(void);
788 void seglist_init(tcb *);
789 void printpacket(int, int, void *, int, struct ip *, void *plast, tcb *tcb);
790 void plotter_vtick(PLOTTER, timeval, u_long);
791 void plotter_utick(PLOTTER, timeval, u_long);
792 void plotter_uarrow(PLOTTER, timeval, u_long);
793 void plotter_tick(PLOTTER, timeval, u_long, char);
794 void plotter_text(PLOTTER, timeval, u_long, char *, char  *);
795 void plotter_temp_color(PLOTTER, char *color);
796 void plotter_ltick(PLOTTER, timeval, u_long);
797 void plotter_rtick(PLOTTER, timeval, u_long);
798 void plotter_rarrow(PLOTTER, timeval, u_long);
799 void plotter_plus(PLOTTER, timeval, u_long);
800 void plotter_perm_color(PLOTTER, char *color);
801 void plotter_line(PLOTTER, timeval, u_long, timeval, u_long);
802 void plotter_larrow(PLOTTER, timeval, u_long);
803 void plotter_htick(PLOTTER, timeval, u_long);
804 void plotter_dtick(PLOTTER, timeval, u_long);
805 void plotter_dot(PLOTTER, timeval, u_long);
806 void plotter_done(void);
807 void plotter_dline(PLOTTER, timeval, u_long, timeval, u_long);
808 void plotter_diamond(PLOTTER, timeval, u_long);
809 void plotter_darrow(PLOTTER, timeval, u_long);
810 void plotter_box(PLOTTER, timeval, u_long);
811 void plotter_arrow(PLOTTER, timeval, u_long, char);
812 void plotter_nothing(PLOTTER, timeval);
813 void plotter_invisible(PLOTTER, timeval, u_long);
814 void plotter_switch_axis(PLOTTER, Bool);
815 void plot_init(void);
816 tcp_pair *dotrace(struct ip *, struct tcphdr *ptcp, void *plast);
817 void PrintRawData(char *label, void *pfirst, void *plast, Bool octal);
818 void PrintRawDataHex(char *label, void *pfirst, void *plast);
819 void PrintTrace(tcp_pair *);
820 void UDPPrintTrace(udp_pair *);
821 void PrintSVHeader(void);
822 void PrintBrief(tcp_pair *);
823 void UDPPrintBrief(udp_pair *);
824 void OnlyConn(int);
825 void IgnoreConn(int);
826 void OnlyUDPConn(int);
827 void IgnoreUDPConn(int);
828 double elapsed(timeval, timeval);
829 void tv_sub(struct timeval *plhs, struct timeval rhs);
830 void tv_add(struct timeval *plhs, struct timeval rhs);
831 int tv_cmp(struct timeval lhs, struct timeval rhs);
832 Bool tv_same(struct timeval lhs, struct timeval rhs);
833 char *elapsed2str(double etime);
834 int ConnReset(tcp_pair *);
835 int ConnComplete(tcp_pair *);
836 u_int SynCount(tcp_pair *ptp);
837 u_int FinCount(tcp_pair *ptp);
838 char *ts2ascii(timeval *);
839 char *ts2ascii_date(timeval *);
840 char *ServiceName(portnum);
841 char *HostName(ipaddr);
842 char *HostAddr(ipaddr);
843 char *HostLetter(llong);
844 char *NextHostLetter(void);
845 char *EndpointName(ipaddr,portnum);
846 PLOTTER new_plotter(tcb *plast, char *filename, char *title,
847 		    char *xlabel, char *ylabel, char *suffix);
848 int rexmit(tcb *, seqnum, seglen, Bool *);
849 enum t_ack ack_in(tcb *, seqnum, unsigned tcp_data_length, u_long eff_win, int ignore);
850 Bool IsRTO(tcb *ptcb, seqnum s);
851 void DoThru(tcb *ptcb, int nbytes);
852 struct mfile *Mfopen(char *fname, char *mode);
853 void Minit(void);
854 int Mfileno(MFILE *pmf);
855 int Mvfprintf(MFILE *pmf, char *format, va_list ap);
856 int Mfwrite(void *buf, u_long size, u_long nitems, MFILE *pmf);
857 long Mftell(MFILE *pmf);
858 int Mfseek(MFILE *pmf, long offset, int ptrname);
859 int Mfprintf(MFILE *pmf, char *format, ...);
860 int Mfflush(MFILE *pmf);
861 int Mfclose(MFILE *pmf);
862 int Mfpipe(int pipes[2]);
863 struct tcp_options *ParseOptions(struct tcphdr *ptcp, void *plast);
864 FILE *CompOpenHeader(char *filename);
865 FILE *CompOpenFile(char *filename);
866 void CompCloseFile(char *filename);
867 void CompFormats(void);
868 int CompIsCompressed(void);
869 Bool FileIsStdin(char *filename);
870 struct tcb *ptp2ptcb(tcp_pair *ptp, struct ip *pip, struct tcphdr *ptcp);
871 void PcapSavePacket(char *filename, struct ip *pip, void *plast);
872 void StringToArgv(char *buf, int *pargc, char ***pargv);
873 void CopyAddr(tcp_pair_addrblock *, struct ip *pip,portnum,portnum);
874 int WhichDir(tcp_pair_addrblock *, tcp_pair_addrblock *);
875 int SameConn(tcp_pair_addrblock *, tcp_pair_addrblock *, int *);
876 Bool ip_cksum_valid(struct ip *pip, void *plast);
877 Bool tcp_cksum_valid(struct ip *pip, struct tcphdr *ptcp, void *plast);
878 Bool udp_cksum_valid(struct ip *pip, struct udphdr *pudp, void *plast);
879 ipaddr *str2ipaddr(char *str);
880 int IPcmp(ipaddr *pipA, ipaddr *pipB);
881 void ModulesPerOldConn(tcp_pair *ptp);
882 
883 /* Memory allocation routines with page boundaries */
884 tcp_pair *MakeTcpPair(void);
885 void FreeTcpPair(tcp_pair *ptr);
886 udp_pair *MakeUdpPair(void);
887 void FreeUdpPair(udp_pair *ptr);
888 seqspace *MakeSeqspace(void);
889 void FreeSeqspace(seqspace *ptr);
890 ptp_snap *MakePtpSnap(void);
891 void FreePtpSnap(ptp_snap *ptr);
892 segment *MakeSegment(void);
893 void FreeSegment(segment *ptr);
894 quadrant *MakeQuadrant(void);
895 void FreeQuadrant(quadrant *ptr);
896 ptp_ptr *MakePtpPtr(void);
897 void FreePtpPtr(ptp_ptr *ptr);
898 void freequad(quadrant **);
899 
900 /* AVL tree support routines */
901 enum AVLRES SnapInsert(ptp_snap **n, ptp_snap *new_node);
902 enum AVLRES SnapRemove(ptp_snap **n, tcp_pair_addrblock address);
903 int AVL_WhichDir(tcp_pair_addrblock *ptpa1, tcp_pair_addrblock *ptpa2);
904 
905 /* high-level line drawing */
906 PLINE new_line(PLOTTER pl, char *label, char *color);
907 void extend_line(PLINE pline, timeval xval, int yval);
908 
909 /* UDP support routines */
910 void udptrace_init(void);
911 void udptrace_done(void);
912 udp_pair *udpdotrace(struct ip *pip, struct udphdr *pudp, void *plast);
913 
914 /* filter routines */
915 void HelpFilter(void);
916 void ParseFilter(char *expr);
917 Bool PassesFilter(tcp_pair *ptp);
918 
919 /* simple string expansion for file names, directories, etc */
920 char *ExpandFormat(const char *format);
921 
922 
923 /* TCP flags macros */
924 #define SYN_SET(ptcp)((ptcp)->th_flags & TH_SYN)
925 #define FIN_SET(ptcp)((ptcp)->th_flags & TH_FIN)
926 #define ACK_SET(ptcp)((ptcp)->th_flags & TH_ACK)
927 #define RESET_SET(ptcp)((ptcp)->th_flags & TH_RST)
928 #define PUSH_SET(ptcp)((ptcp)->th_flags & TH_PUSH)
929 #define URGENT_SET(ptcp)((ptcp)->th_flags & TH_URG)
930 #define FLAG6_SET(ptcp)((ptcp)->th_flags & 0x40)
931 #define FLAG7_SET(ptcp)((ptcp)->th_flags & 0x80)
932 
933 /* Changed the following macros to reflect the correct position
934 of bits as specified in RFC 2481 and draft-ietf-tsvwg-ecn-04.txt */
935 /*
936 	#define CWR_SET(ptcp)     (TH_X2((ptcp)) & TH_CWR)
937 	#define ECN_ECHO_SET(ptcp)(TH_X2((ptcp)) & TH_ECN_ECHO)
938 */
939 
940 #define CWR_SET(ptcp)	(TH_FLAGS((ptcp)) & TH_CWR)
941 #define ECN_ECHO_SET(ptcp)	(TH_FLAGS((ptcp)) & TH_ECN_ECHO)
942 
943 /* connection directions */
944 #define A2B 1
945 #define B2A -1
946 
947 /* If the AVL node is to left or right in the AVL tree */
948 /* Words "LEFT" and "RIGHT" have already been taken in an enum
949  * above. Let us call them LT, RT just not to make it ambiguous for ourselves
950  * or the compiler or both :-)
951  */
952 #define LT -2
953 #define RT 2
954 
955 /*macros for maintaining the seqspace used for rexmit*/
956 #define QUADSIZE	(0x40000000)
957 #define QUADNUM(seq)	((seq>>30)+1)
958 #define IN_Q1(seq)	(QUADNUM(seq)==1)
959 #define IN_Q2(seq)	(QUADNUM(seq)==2)
960 #define IN_Q3(seq)	(QUADNUM(seq)==3)
961 #define IN_Q4(seq)	(QUADNUM(seq)==4)
962 #define FIRST_SEQ(quadnum)	(QUADSIZE*(quadnum-1))
963 #define LAST_SEQ(quadnum)	((QUADSIZE*quadnum)-1) /* bug fix by Priya */
964 #define BOUNDARY(beg,fin) (QUADNUM((beg)) != QUADNUM((fin)))
965 
966 
967 /* physical layers currently understood					*/
968 #define PHYS_ETHER	1
969 #define PHYS_FDDI       2
970 
971 /*
972  * SEQCMP - sequence space comparator
973  *	This handles sequence space wrap-around. Overlow/Underflow makes
974  * the result below correct ( -, 0, + ) for any a, b in the sequence
975  * space. Results:	result	implies
976  *			  - 	 a < b
977  *			  0 	 a = b
978  *			  + 	 a > b
979  */
980 #define	SEQCMP(a, b)		((long)(a) - (long)(b))
981 #define	SEQ_LESSTHAN(a, b)	(SEQCMP(a,b) < 0)
982 #define	SEQ_GREATERTHAN(a, b)	(SEQCMP(a,b) > 0)
983 
984 
985 /* SACK TCP options (not an RFC yet, mostly from draft and RFC 1072) */
986 /* I'm assuming, for now, that the draft version is correct */
987 /* sdo -- Tue Aug 20, 1996 */
988 #define	TCPOPT_SACK_PERM 4	/* sack-permitted option */
989 #define	TCPOPT_SACK      5	/* sack attached option */
990 #define	MAX_SACKS       10	/* max number of sacks per segment (rfc1072) */
991 typedef struct sack_block {
992     seqnum	sack_left;	/* left edge */
993     seqnum	sack_right;	/* right edge */
994 } sack_block;
995 
996 #define MAX_UNKNOWN 16
997 typedef struct opt_unknown {
998     u_char	unkn_opt;
999     u_char	unkn_len;
1000 } opt_unknown;
1001 
1002 /* RFC 1323 TCP options (not usually in tcp.h yet) */
1003 #define	TCPOPT_WS	3	/* window scaling */
1004 #define	TCPOPT_TS	8	/* timestamp */
1005 
1006 /* other options... */
1007 #define	TCPOPT_ECHO		6	/* echo (rfc1072) */
1008 #define	TCPOPT_ECHOREPLY	7	/* echo (rfc1072) */
1009 #define TCPOPT_TIMESTAMP	8	/* timestamps (rfc1323) */
1010 #define TCPOPT_CC		11	/* T/TCP CC options (rfc1644) */
1011 #define TCPOPT_CCNEW		12	/* T/TCP CC options (rfc1644) */
1012 #define TCPOPT_CCECHO		13	/* T/TCP CC options (rfc1644) */
1013 
1014 /* RFC 2481 (ECN) IP and TCP flags (not usually defined yet) */
1015 #define IPTOS_ECT	0x02	/* ECN-Capable Transport */
1016 #define IPTOS_CE	0x01	/* Experienced Congestion */
1017 
1018 // Modified the following macros to reflect the
1019 // correct bit positions for CWR and ECE as specified in
1020 // RFC 2481 and the latest draft: draft-ietf-tsvwg-ecn-04.txt.
1021 // The bits CWR and ECE are actually the most significant
1022 // bits in the TCP flags octet respectively.
1023 
1024 /*#define TH_ECN_ECHO	0x02 */	/* Used by receiver to echo CE bit */
1025 /*#define TH_CWR		0x01 */	/* Congestion Window Reduced */
1026 
1027 #define TH_CWR 0x80			/* Used by sender to indicate congestion
1028 							   window size reduction. */
1029 #define TH_ECN_ECHO 0x40	/* Used by receiver to echo CE bit. */
1030 
1031 
1032 /* some compilers seem to want to make "char" unsigned by default, */
1033 /* which is breaking stuff.  Rather than introduce (more) ugly */
1034 /* machine dependencies, I'm going to FORCE some chars to be */
1035 /* signed... */
1036 typedef signed char s_char;
1037 
1038 struct tcp_options {
1039     short	mss;		/* maximum segment size 	*/
1040     s_char	ws;		/* window scale (1323) 		*/
1041     long	tsval;		/* Time Stamp Val (1323)	*/
1042     long	tsecr;		/* Time Stamp Echo Reply (1323)	*/
1043 
1044     Bool	sack_req;	/* sacks requested 		*/
1045     s_char	sack_count;	/* sack count in this packet */
1046     sack_block	sacks[MAX_SACKS]; /* sack blocks */
1047 
1048     /* echo request and reply */
1049     /* assume that value of -1 means unused  (?) */
1050     u_long	echo_req;
1051     u_long	echo_repl;
1052 
1053     /* T/TCP stuff */
1054     /* assume that value of -1 means unused  (?) */
1055     u_long	cc;
1056     u_long	ccnew;
1057     u_long	ccecho;
1058 
1059     /* record the stuff we don't understand, too */
1060     char	unknown_count;	/* number of unknown options */
1061     opt_unknown	unknowns[MAX_UNKNOWN]; /* unknown options */
1062 };
1063 
1064 
1065 
1066 /*
1067  * File extensions to use
1068  *
1069  */
1070 #define RTT_DUMP_FILE_EXTENSION		"_rttraw.dat"
1071 #define RTT_GRAPH_FILE_EXTENSION	"_rtt.xpl"
1072 #define PLOT_FILE_EXTENSION		"_tsg.xpl"
1073 #define SEGSIZE_FILE_EXTENSION		"_ssize.xpl"
1074 #define OWIN_FILE_EXTENSION		"_owin.xpl"
1075 #define TLINE_FILE_EXTENSION		"_tline.xpl"
1076 #define THROUGHPUT_FILE_EXTENSION	"_tput.xpl"
1077 #define CONTENTS_FILE_EXTENSION		"_contents.dat"
1078 #define RECVWIN_FILE_EXTENSION		"_rwin.xpl"
1079 
1080 /* name of file to store filtered output into */
1081 #define PASS_FILTER_FILENAME		"PF"
1082 
1083 /* name of the resource file */
1084 #define TCPTRACE_RC_FILE ".tcptracerc"
1085 
1086 /* name of the argument envariable */
1087 #define TCPTRACE_ENVARIABLE "TCPTRACEOPTS"
1088 
1089 /* packet-reading options... */
1090 /* the type for a packet reading routine */
1091 typedef int pread_f(struct timeval *, int *, int *, void **,
1092 		   int *, struct ip **, void **);
1093 
1094 /* give the prototypes for the is_GLORP() routines supported */
1095 #ifdef GROK_SNOOP
1096 	pread_f *is_snoop(char *);
1097 #endif /* GROK_SNOOP */
1098 #ifdef GROK_NETM
1099 	pread_f *is_netm(char *);
1100 #endif /* GROK_NETM */
1101 #ifdef GROK_TCPDUMP
1102 	pread_f *is_tcpdump(char *);
1103 #endif /* GROK_TCPDUMP */
1104 #ifdef GROK_ETHERPEEK
1105 	pread_f *is_EP(char *);
1106 #endif /* GROK_ETHERPEEK */
1107 #ifdef GROK_NS
1108  	pread_f *is_ns(char *);
1109 #endif /* GROK_NS */
1110 #ifdef GROK_NLANR
1111 	pread_f *is_nlanr(char *);
1112 #endif /* GROK_NLANR */
1113 #ifdef GROK_NETSCOUT
1114 	pread_f *is_netscout(char *);
1115 #endif /* GROK_NETSCOUT */
1116 #ifdef GROK_ERF
1117 	pread_f *is_erf(char *);
1118 #endif /* GROK_ERF */
1119 
1120 #ifndef __VMS
1121 /* I've had problems with the memcpy function that gcc stuffs into the program
1122    and alignment problems.  This should fix it! */
1123 void *MemCpy(void *p1, void *p2, size_t n); /* in tcptrace.c */
1124 #define memcpy(p1,p2,n) MemCpy(p1,p2,n)
1125 #endif /* __VMS */
1126 
1127 #ifdef __VMS
1128 #define snprintf snprintf_vms
1129 int snprintf_vms(char *str, size_t len, const char *fmt, ...);
1130 #endif
1131 
1132 /*
1133  * timeval compare macros
1134  */
1135 #define tv_ge(lhs,rhs) (tv_cmp((lhs),(rhs)) >= 0)
1136 #define tv_gt(lhs,rhs) (tv_cmp((lhs),(rhs)) >  0)
1137 #define tv_le(lhs,rhs) (tv_cmp((lhs),(rhs)) <= 0)
1138 #define tv_lt(lhs,rhs) (tv_cmp((lhs),(rhs)) <  0)
1139 #define tv_eq(lhs,rhs) (tv_cmp((lhs),(rhs)) == 0)
1140 
1141 /* handy constants */
1142 #define US_PER_SEC 1000000	/* microseconds per second */
1143 #define MS_PER_SEC 1000		/* milliseconds per second */
1144 
1145 
1146 /*
1147  * Macros to simplify access to IPv4/IPv6 header fields
1148  */
1149 #define PIP_VERS(pip) (IP_V((struct ip *)(pip)))
1150 #define PIP_ISV6(pip) (PIP_VERS(pip) == 6)
1151 #define PIP_ISV4(pip) (PIP_VERS(pip) == 4)
1152 #define PIP_V6(pip) ((struct ipv6 *)(pip))
1153 #define PIP_V4(pip) ((struct ip *)(pip))
1154 #define PIP_EITHERFIELD(pip,fld4,fld6) \
1155    (PIP_ISV4(pip)?(PIP_V4(pip)->fld4):(PIP_V6(pip)->fld6))
1156 #define PIP_LEN(pip) (PIP_EITHERFIELD(pip,ip_len,ip6_lngth))
1157 
1158 /*
1159  * Macros to simplify access to IPv4/IPv6 addresses
1160  */
1161 #define ADDR_VERSION(paddr) ((paddr)->addr_vers)
1162 #define ADDR_ISV4(paddr) (ADDR_VERSION((paddr)) == 4)
1163 #define ADDR_ISV6(paddr) (ADDR_VERSION((paddr)) == 6)
1164 struct ipaddr *IPV4ADDR2ADDR(struct in_addr *addr4);
1165 struct ipaddr *IPV6ADDR2ADDR(struct in6_addr *addr6);
1166 
1167 /*
1168  * Macros to check for congestion experienced bits
1169  */
1170 #define IP_CE(pip) (((struct ip *)(pip))->ip_tos & IPTOS_CE)
1171 #define IP_ECT(pip) (((struct ip *)(pip))->ip_tos & IPTOS_ECT)
1172 
1173 /*
1174  * fixes for various systems that aren't exactly like Solaris
1175  */
1176 #ifndef IP_MAXPACKET
1177 #define IP_MAXPACKET 65535
1178 #endif /* IP_MAXPACKET */
1179 
1180 /* max 32 bit number */
1181 #define MAX_32 (0x100000000LL)
1182 
1183 #ifndef ETHERTYPE_REVARP
1184 #define ETHERTYPE_REVARP        0x8035
1185 #endif /* ETHERTYPE_REVARP */
1186 
1187 #ifndef ETHERTYPE_VLAN
1188 #define ETHERTYPE_VLAN		0x8100
1189 #endif	/* 802.1Q Virtual LAN */
1190 
1191 #ifndef ETHER_VLAN_ENCAP_LEN
1192 #define ETHER_VLAN_ENCAP_LEN	4
1193 #endif /* 802.1Q tag header length */
1194 
1195 /* support for PPPoE encapsulation added by Yann Samama (ysamama@nortelnetworks.com)*/
1196 #ifndef ETHERTYPE_PPPOE_SESSION
1197 #define ETHERTYPE_PPPOE_SESSION	0x8864
1198 #endif /* PPPoE ether type */
1199 #ifndef PPPOE_SIZE
1200 #define PPPOE_SIZE		22
1201 #endif /* PPPOE header size */
1202 
1203