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