/* 1102, Tue 20 Feb 01 (EST)

   PKTSNAP.H:  Declarations for AU packet monitoring
          extensions to Waterloo TCP/IP

   Copyright (C) 1992-2002 by Nevil Brownlee,
   CAIDA | University of Auckland */

/*
 * $Log: pktsnap.h,v $
 * Revision 1.1.1.2.2.12  2002/02/23 01:57:34  nevil
 * Moving srl examples to examples/ directory.  Modified examples/Makefile.in
 *
 * Revision 1.1.1.2.2.10  2001/05/24 02:19:57  nevil
 * LfapMet implemented by Remco Poortinga.
 * MinPDUs implemented by Nevil.
 *
 * Revision 1.1.1.2.2.8  2000/08/08 19:44:56  nevil
 * 44b8 release
 *
 * Revision 1.1.1.2.2.3  2000/06/06 03:38:23  nevil
 * Combine NEW_ATR with TCP_ATR, various bug fixes
 *
 * Revision 1.1.1.2.2.1  2000/01/12 02:57:14  nevil
 * Implement 'packet pair matched' turnaroundtime distribution attributes.
 * Fix ASN-related bugs in NeTraMet, distribution-related bugs in fd_filter.
 *
 * Revision 1.1.1.2  1999/10/03 21:06:27  nevil
 * *** empty log message ***
 *
 * Revision 1.1.1.1.2.6  1999/09/22 05:38:44  nevil
 * Improve code to work properly on 64-bit machines
 * - Add OS=ALPHA handling to configure.in
 * - Clean up the Alpha compiler warnings
 * - Change all the snmp-related code to use Bit32 instead of unsigned long
 *
 * Revision 1.1.1.1.2.5  1999/05/26 02:41:42  nevil
 * Integrate V6 and ASN code into PC versions of the meter.
 * This required a rework of the makefiles, using @cflags.opt files
 * to provide a much longer command line to the Borland C compiler.
 *
 * Revision 1.1.1.1.2.4  1999/05/18 03:36:29  nevil
 * Implement IPv6 in NeTraMet, and its manager/collectors.
 * - This is controlled by the V6 #define
 * - NeTraMet recognises v6 packets and fishes through their extension
 *     headers until it finds the actual payload.
 * - NeMaC et al display v6 addresses in the fom specified by RFC 2373
 * - fd_util and fd_extract allow colons in addresses (for defining tags)
 *
 * Revision 1.1.1.1.2.3  1999/02/15 21:24:09  nevil
 * Distribution file for 4.3b9
 *
 * Revision 1.1.1.1.2.2  1999/01/08 01:31:57  nevil
 * Implementation of TCP attributes, part 3
 *
 * Revision 1.1.1.1.2.1  1998/11/25 03:30:14  nevil
 * Fix endian problems in NetFlowMet
 *
 * Revision 1.1.1.1  1998/11/16 03:57:29  nevil
 * Import of NeTraMet 4.3b3
 *
 * Revision 1.1.1.1.2.1  1998/11/11 23:14:47  nevil
 * Only include malloc.h if we HAVE_MALLOC_H
 *
 * Revision 1.1.1.1  1998/10/28 20:31:29  nevil
 * Import of NeTraMet 4.3b1
 *
 * Revision 1.1.3.1.2.2  1998/10/19 22:32:50  nevil
 * Meter improvements, mostly arising from developments for the
 * OCxMON meter.  These are documented in notes_oc.txt
 *
 * Revision 1.1.3.1.2.1  1998/10/18 20:51:29  nevil
 * Added Nicolai's patches, some 'tidying up' of the source
 *
 * Revision 1.1.3.1  1998/10/13 02:48:44  nevil
 * Import of Nicolai's 4.2.2
 *
 * Revision 1.1.1.1  1998/08/24 12:09:29  nguba
 * NetraMet 4.2 Original Distribution
 */

#if TIME_WITH_SYS_TIME
#include <time.h>
#include <sys/time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
else
#include <time.h>
#endif
#endif

#ifdef PKTSNAP
#define EXTERN
#else
#define EXTERN extern
#endif

#if defined(NETFLOW)
#  if (NETFLOW & 0x01) != 0
#     define NF_ASN_ATT      1
#  endif
#  if (NETFLOW & 0x02) != 0
#     define NF_OTHER_ATT    1
#  endif
#  if (NETFLOW & 0x04) != 0
#     define NF_CISCO_DATA   1
#  endif
#  if (NETFLOW & 0x08) != 0
#     define NF_OCX_BGP      1
#  endif
#endif 

#if defined(OCX)
#  if (OCX & 0x01) != 0
#     define OCX_NTM         1
#  endif
#  if (OCX & 0x02) != 0
#     define FLAT_MEM        1
#  endif
#  if (OCX & 0x04) != 0
#     define OC3_NTM         1
#  endif
#endif 

#if defined(CORAL)
#  if (CORAL & 0x01) != 0
#     define CR_DATA         1
#  endif
#endif 

#if defined(DAG)
#  if (DAG & 0x01) != 0
#     define DAG_DATA        1
#  endif
#  if (DAG & 0x02) != 0
#     define DAG_ADSL        1
#  endif
#endif 

/* Determining snapshot length:  (Nevil, 9 Apr 98)

   Worst case IP packet:       Minimal IP packet:
        14  Ethernet                14  Ethernet
         8  802.2 + SNAP             8  802.2 + SNAP
        60  IP header               20  IP header
        20  TCP header              20  TCP header
      ----                       -----
       102  bytes                   62  bytes

   Leaving out Ethernet and 802.2 headers (22 bytes),
   the peer header lengths are:
      IP4:   80 bytes
      CLNS:  53 bytes  (12 header + 2x21 NSAPs)  */

/* IPv6 headers - RFC 2460: (Nevil, 17 May 99)

   40 bytes IPv6 header, includes payload length (rest of packet)

   Followed by extension headers, identified by Next Header field:
   Extension headers are multiples of 8 bytes long

   Minimal IPv6 header length is thus 40 bytes (no extension headers)
   Worst case could be a LOT bigger!
   120 bytes seems a reasonable guess to start with */

#define MAC_ADDR_LEN     6  /* Address lengths */
#define SNAP_MAC  2*MAC_ADDR_LEN

#if defined(SOLARIS23)
# define SNAPSIZE   54L  /* Enough for all except CLNS (which needs 70) */
/* SNAP size currently set to 54 to sidestep a bug in Solaris 2.3, 
   which corrupts packets smaller than the SNAP size.  This bug is 
   fixed in Solaris 2.4; if you are using Solaris 2.3 you should
   set SNAPSIZE to MXPKTHDRLEN.   Nevil, 12 Jul 94 */

#elif V6
# define SNAPSIZE  142  /* First guess - see comments above */

#elif defined(DOS)
# define SNAPSIZE  54  /* Packet Driver source: 8390.asm */

#elif OCX_NTM || OC3_NTM
# define SNAPSIZE  SNAP_MAC + 48  /* Kludged MACs + first AAL5 cell */

#else
# define SNAPSIZE 102  /* Worst case IP, as above */
#endif

EXTERN int pktsize;   /* Snapshot - header */

#define IP4_ADDR_LEN     4
#define IP6_ADDR_LEN    16
#define DN_ADDR_LEN      3
#define ET_ADDR_LEN      3
#if FULL_IPX
# define IPX_ADDR_LEN   10  /* 4 Novell net nbr + 6 E/N address */
#else
# define IPX_ADDR_LEN    4  /* Only use the Novell net nbr */
#endif
#define NSAP_ADDR_LEN   20

#define TRANS_ADDR_LEN   2

#if CLNS
# define PEER_ADDR_LEN  NSAP_ADDR_LEN
# define RULE_ADDR_LEN  NSAP_ADDR_LEN
#elif V6 || FULL_IPX
# define PEER_ADDR_LEN   IP6_ADDR_LEN
# define RULE_ADDR_LEN   IP6_ADDR_LEN
#else  /* v4 */
# define PEER_ADDR_LEN   IP4_ADDR_LEN
# define RULE_ADDR_LEN   MAC_ADDR_LEN
#endif

#define QBYTE_PEER  (PEER_ADDR_LEN == IP4_ADDR_LEN)

union MAC_address {  /* RTFM rule addresses (can hold any address type) */
   Bit32  ms4;
#if WORDS_BIGENDIAN
   Bit16  rsv, ls2;
#else
   Bit16  ls2, rsv;
#endif
   };

union address {
   Bit8   rule[RULE_ADDR_LEN];
   union MAC_address  ma;
   Bit32  peer32[(PEER_ADDR_LEN+3)/4];
   Bit32  qbyte;
   Bit16  trans;
   Bit8   byte;
   };

#if NEW_ATR
struct tcp_header {
#if 0
   Bit16 srcPort;
   Bit16 dstPort;
#endif
   Bit32 seqnum;
   Bit32 acknum;
   Bit16 flags;
   Bit16 window;
# if 0
   Bit16 checksum;
   Bit16 urgentPointer;
# endif
  };

#define tcp_FlagHLEN  0xF000
#define tcp_dataoffset(f)  (((f) >> 10) & 0x003C)

#define tcp_FlagALL   0x003F
#define tcp_FlagURG   0x0020
#define tcp_FlagACK   0x0010
#define tcp_FlagPUSH  0x0008
#define tcp_FlagRST   0x0004
#define tcp_FlagSYN   0x0002
#define tcp_FlagFIN   0x0001

#endif  /* NEW_ATR */

struct pkt_key {
   union address PeerAddress;
   Bit32 AdjAddr_ms4;  Bit16 AdjAddr_ls2;  
   Bit16 TransAddress;
   Bit8 Interface, AdjType;
#if NF_ASN_ATT
   Bit16 nf_ASN;
   Bit8 nf_mask, rsv1;
#endif
   };

#define INV_ADJ    0x04  /* Indicator bits for invalid_addrs */
#define INV_PEER   0x02
#define INV_TRANS  0x01

struct pkt {
   unsigned int next;  /* For linking into queues */

   struct pkt_key Low, High;
   unsigned char PeerAddrType, TransAddrType;
   unsigned char DSCodePoint;
   unsigned char invalid_addrs;

#if NF_CISCO_DATA
   unsigned char ntm_interface;  /* Index in  -i  list */
   unsigned long dPkts, dOctets;
   unsigned long dFirst, dLast;
#elif LFAP_METER
   unsigned char ntm_interface;  /* Index in  -i  list */
   unsigned long dPackets_recvd,dPackets_sent;
   unsigned long dOctets_recvd,	dOctets_sent;
   unsigned long FirstTime, LastTime;
#else
#define ntm_interface  Low.Interface
#endif
   unsigned int p_len;
#if OCX_NTM || OC3_NTM
   double arrival_time;
#elif defined(DOS)
   counter64 arrival_time;
#elif DAG_DIRECT
   long long arrival_time;
#else  /* Unix */
   struct timeval arrival_time;
#endif

#if NEW_ATR
   union {
      struct {
         Bit16 ident;
         Bit16 sequence;
         } icmp;
      union {
	 struct {
            Bit16 ident;  /* Set by requestor */
            Bit8 p0;
#  define      dns_resp        0x80  /* 0=query, 1=response */
#  define      dns_query_type  0x78  /* 0=standard, 8=inverse */
            Bit8 p1;
#  define      dns_resp_type   0x0F  /* 0=OK, 1=FmtErr, 
                                        2=ServFail, 3=NotFound */
	    } dns;
	 struct {
	    } snmp;
         } udp;
      struct {
         struct tcp_header th;
         Bit16 tcp_len;  /* IP length - (IP header and options) */
         } tcp;
      } pi;  /* Packet info */
#endif  /* NEW_ATR */

  Bit8 pktinfo_sz;  /* Nbr of bytes of packet info */
   };  /* struct pkt */

#if defined(DOS)

/* Declared in wattcp\src\pcpkt.c .. */

extern unsigned char eth_addr[6];
#endif

/* Declared in wattcp\acct\meter_pc.c .. */

EXTERN Bit32  /* Statistics variables */
   max_pkt_rate, pkt_backlog,max_pkt_backlog,
   mdpacketrate, stats_time, t_backlog,  
   badpackets,nobufpackets;
EXTERN int chart_interface;
EXTERN unsigned long
   spackets,sbytes, zpackets;
EXTERN int
   clear_pkt_stats;  /* 1 to clear stats variables */

/* 12 bytes interframe space + 8 bytes preamble + 4 byte FCS */
#define util_pc(p,b)  (((24l*p + b)/1250l + 5l)/10l)  /* % utilisation */

#ifdef DOS  /* Variables for meter 'idle %' statistics */
EXTERN Bit32
   dummypackets,
   kilodummypackets, dummypacketrate, mindummyrate;
#else
EXTERN clock_t
   realtime, realtime_org, srealtime,
   proctime, proctime_org, sproctime,
   min_idle1000;
#endif

EXTERN int
   scr_lrow,      /* Y co-ord: bottom line of screen */
   scr_mtrow,     /* Y co-ord: top line of status message area */
   scr_lcol,      /* X co-ord: rightmost col of screen */
   scr_chrtcol;   /* X co-ord: leftmost col of chart */

#ifndef DOS
#define w_roll(x1,y1, x2,y2, up)  /* PC screen functions */
#define w_clear(x1,y1, x2,y2)

void start_uptime_clock(void);
Bit32 uptime_s(void);
Bit32 uptime_cs(void);

# if DAG_DIRECT
double centiseconds(long long nt);
double microseconds(long long nt);
# else
double centiseconds(struct timeval nt);
double microseconds(struct timeval nt);
# endif

#else

#ifdef __cplusplus
extern "C" {  // chart.cpp functions
#endif
   int kbstatus(void);
   unsigned char kbcode(void);
   void bios_scroll(int way, int tx,int ty, int bx,int by, int nrows, int attr);
   void scinit(void);
   void scpos(int x, int y);
   void set_tod(void);
   void sclear(void);
   void swrite(int c);
   void w_clear(int tx,int ty, int bx,int by);
   void w_roll(int tx,int ty, int bx,int by, int n);
   void chart(int tx,int ty, int bx,int by, int x1,int x2,int x3);

   void start_uptime_clock(void);
   Bit32 uptime_s(void);
   Bit32 uptime_cs(void);

#if OCX_NTM || OC3_NTM
   double uptime(void);
   double centiseconds(double s);
   double microseconds(double s);
#else
   double centiseconds(counter64 nt);
   double microseconds(counter64 nt);
#endif
#ifdef __cplusplus
   };
#endif
#endif

/* Monitor variables .. */

EXTERN Bit32 npackets;
EXTERN Bit32 lostpackets;

#define MAXPKTLEN  1526

#if defined(DOS)
EXTERN struct pkt far *pkts;
EXTERN int
   maxpkt,       /* Size of meter input buffer */
   free_n_pkt,   /* Available pkt stack */
      free_head,free_tail,
   proc_n_pkt,   /* Queue of pkts to be processed */
      proc_head,proc_tail;
#endif

EXTERN Bit32 l_tod;  /* Time of day */
EXTERN int tod_h,tod_m,tod_s,
   s_tod_h,s_tod_m,s_tod_s;  /* Time when counters last saved */

EXTERN Bit32 elapsed_sec;  /* Seconds since counters last saved */

#ifndef NULL
#define NULL  0
#endif
