/*  globdefs.h          (c) Steve Adam 1995         steve@netinfo.com.au
 *
 *  Various global definitions.
 *
 *  Should probably be first header included after the <standard> stuff
 *
 *  I decided to put the various header data structures in here too
 */

#include <time.h>
#include "device.h"

#define TCP_DRIVER_VERSION	"01.11"

/*
 *  A sensible concession to portability and clarity.
 */

typedef char int8;
typedef unsigned char uint8, octet;
typedef int int16;
typedef unsigned int uint16;
typedef long int32;
typedef unsigned long uint32;


/* TCP defines */

#define MAXINT16    65535L
#define	MSL2        30  /* Guess at two maximum-segment lifetimes   */
#define	TWAIT_DEF   15  /* Default wait time for TTIME_WAIT state   */
#define	MIN_RTO   500L  /* Minimum timeout, milliseconds            */

#define MAX_STATES	12 	/* was 16 must be > 2 and < 256 */
#define MAX_HDR		128	/* XXX 4bsd-ism: should really be 128 */

/* IP defines */

#define IP_MAXOPT	40	/* Largest option field, bytes */

/* Fields in option type byte */
#define	OPT_COPIED	0x80	/* Copied-on-fragmentation flag */
#define	OPT_CLASS	0x60	/* Option class */
#define	OPT_NUMBER	0x1f	/* Option number */

/* IP option numbers */
#define	IP_EOL		0	/* End of options list */
#define	IP_NOOP		1	/* No Operation */
#define	IP_SECURITY	2	/* Security parameters */
#define	IP_LSROUTE	3	/* Loose Source Routing */
#define	IP_TIMESTAMP	4	/* Internet Timestamp */
#define	IP_RROUTE	7	/* Record Route */
#define	IP_STREAMID	8	/* Stream ID */
#define	IP_SSROUTE	9	/* Strict Source Routing */

/* Timestamp option flags */
#define	TS_ONLY		0	/* Time stamps only */
#define	TS_ADDRESS	1	/* Addresses + Time stamps */
#define	TS_PRESPEC	3	/* Prespecified addresses only */


/*  Atari standard Bios devices */

#define CON    2   /* Console keyboard/display, output, and input */


/*  It is taken for granted that my C compiler creates these structures
 *  in exactly the order shown.  Other compilers *probably* do too.
 */

/* The minimum IP header
*/

typedef struct ip_header {
	unsigned ver : 4;		/*  Version                                     */
	unsigned ihl : 4;		/*  Internet Header Length                      */
	unsigned tos : 8;		/*  Type of Service                             */
    int16  len;            /*  Total length, 16 bits                       */
    uint16  id;             /*  Identification, 16 bits                     */
    int16  ofst;           /*  Fragment offset, 16 bits, includes Flags    */
    uint8   ttl;            /*  Time to live, 8 bits                        */
    uint8   ptcl;           /*  Protocol, 8 bits                            */
    uint16  sum;            /*  Header checksum, 16 bits                    */
    uint32  s_ip;           /*  Source Address, 32 bits                     */
    uint32  d_ip;           /*  Destination Address, 32 bits                */
   	/*char optlen;		 Length of options field, bytes */
	/*char options[IP_MAXOPT]; Options field */
} IP_HDR;

/* len and ofst used to be uint16 */

/*  IP version number.  */

#define IP_VERSION  4

#define	SLF_ESC		0x01		/* next char is escaped */
#define SLF_DROP	0x02		/* drop this packet */
#define SLF_LINKED	0x04		/* interface is linked to device */
#define SLF_COMPRESS	0x08		/* turn on VJ compression */
#define SLF_AUTOCOMP	0x10		/* enable comp. on TCP_UNCOMP. frame */
#define SLF_COMPCID	0x20		/* enable CID compression */
#define SLF_USRMASK	(SLF_COMPRESS|SLF_AUTOCOMP|SLF_COMPCID)

/*  Values for IP header Protocol field    */
#define P_ICMP   1
#define P_TCP    6
#define P_UDP   17

/* packet types */
#define TYPE_IP			0x40
#define TYPE_UNCOMPRESSED_TCP	0x70
#define TYPE_COMPRESSED_TCP	0x80
#define TYPE_ERROR		0x00

/* well-defined IP protocols */
#define IPPROTO_IP	0
#define IPPROTO_ICMP	1
#define IPPROTO_TCP	6
#define IPPROTO_UDP	17
#define IPPROTO_RAW	255
#define IPPROTO_MAX	IPPROTO_RAW

#define IS_INET_PROTO(p) \
	((p) == IPPROTO_ICMP || (p) == IPPROTO_TCP || (p) == IPPROTO_UDP)

/* well-known IP ports */
#define IPPORT_RESERVED		1024
#define IPPORT_USERRESERVED	5000

/*  Fragment flags  (or'd with fragment field) */
#define FLAG_LF 0x0000
#define FLAG_DF 0x4000
#define FLAG_MF 0x2000

/* flag values */
#define SLF_TOSS 1		/* tossing rcvd frames because of input err */


/*  ICMP Subheader structure.
 *
 *      Note that the Second half of the ICMP header has different
 *  meaning depending on circumstance.  I have labelled it as
 *  Identifier and Sequence because they are the only uses I
 *  intend to make of it.
 */

typedef struct icmp_header {
    uint8   type;           /*  Icmp message type                           */
    uint8   code;           /*  Various meanings depending on Type          */
    uint16  sum;            /*  Checksum of the ICMP header and data        */
    uint16  id;             /*  Packet identifier (For ping etc.)           */
    uint16  seq;            /*  Packet sequence (For ping etc.)             */
} ICMP_HDR;

typedef struct tcp_header {
    uint16  sport;          /* Source Port                      */
    uint16  dport;          /* Destination Port                 */
/* URAn NB: I changed 'seq' & 'ack' below back to signed long */
    int32  seq;             /* Sequence Number                  */
    int32  ack;             /* Acknowledge Number               */
	unsigned ofst : 4;		/* Offset to TCP data in longs		*/
	unsigned : 6;			/* Filler bits (reserved)			*/
	unsigned f_urg  : 1;	/* URG flag							*/
	unsigned f_ack  : 1;	/* ACK flag							*/
	unsigned f_psh  : 1;	/* PSH flag							*/
	unsigned f_rst  : 1;	/* RST flag							*/
	unsigned f_syn  : 1;	/* SYN flag							*/
	unsigned f_fin  : 1;	/* FIN flag							*/
    uint16  window;         /* Current Window Size              */
    uint16  sum;            /* Checksum Field                   */
    uint16  urgent;         /* Urgent Pointer                   */
} TCP_HDR;



typedef struct udp_header {
    uint16  sport;          /*  Udp Source Port             */
    uint16  dport;          /*  Udp Destination Port        */
    uint16  length;         /*  Udp header + data length    */
    uint16  sum;            /*  Checksum incl. pseudo hdr   */
} UDP_HDR;


/* Pseudo header for TCP and UDP checksum calculations      */

typedef struct pseudo_header {
    uint32  s_ip;                   /* Source IP address        */
    uint32  d_ip;                   /* Destination IP address   */
    uint16  ptcl;                   /* Protocol (P_UDP, P_TCP)  */
    uint16  len;                    /* Message + hdr size       */
} PH;


/* Generic Packet structure
 *  *Every* packet processed by this system will
 *  will reside in a GPKT structure.
 *  Some of the elements of this structure will be specific
 *  to particular parts of the code.  Other code will ignore
 *  them entirely.
 *
 *  If this changes, update initialiser packet in packet.c
 */

typedef struct gpkt {
    char    *fp;        /*  Pointer to start of packet for KRfree()         */
    char    *pip;       /*  Points to an IP pkt or NULL  (ie: base of pkt)  */
    char    *mp;        /*  Points to message. (ie: Following IP header)    */
    char    *data;      /*  Points actual data (ie: After all headers)      */
    int16   ip_len;     /*  Length of the IP packet.  (Including header)    */
    int16   mlen;       /*  Generic message contents size                   */
    int16   dlen;       /*  Size of data space that follows all headers.    */
    struct  gpkt *next; /*  Points to next gpkt in queue or NULL            */
} GPKT ;

#define GPNULL  (GPKT *)NULL


typedef struct output_queue {
    uint16 size;            /* Size of buffer               */
    uint16 cnt;             /* Count of bytes in buffer     */
    uint16 nw;              /* Next pos to write into buf   */
    uint16 nr;              /* Next pos to read from buf    */
    char   buf[0];          /* Ptr to the actual buffer     */
} OUTQ;

/*  The TCP TCB and related structures  */

typedef struct tcp_tcb {
    GPKT    *pq;            /*  The pend queue (For incoming out of order)  */
    OUTQ    *outq;          /*  TCP output queue                            */
    uint16  rmss;           /*  Remote Max segment size.  Default 536       */
    uint16  tos;            /*  Type of service for this connection         */
    uint8   type;           /*  Type of ICMP error packet                   */
    uint8   code;           /*  Code of ICMP error packet                   */
    struct {
        uint32  una;        /*  Send unacknowledged                         */
        uint32  nxt;        /*  Send next                                   */
        uint32  ptr;        /*  */
        uint32  wl1;        /*  Sequence number used for last window update */
        uint32  wl2;        /*  Ack number used for last window update      */
        uint16  wnd;        /*  Send Window                                 */
        uint16  up;         /*  Send Urgent Pointer                         */
    } snd;
    uint32  iss;            /*  Initial Send sequence number                */
    struct {
        uint32  nxt;        /*  Receive next                                */
        uint16  wnd;        /*  Receive window                              */
        uint16  up;         /*  Receive Urgent Pointer                      */
    } rcv;
    uint32  irs;            /*  Initial receive sequence number             */
    int16   backoff;        /*  Powers of two to multiply RTO by.           */
    uint16  prc;            /*  Precedence value.                           */
    int16   dupacks;        /*  Duplicate Ack count                         */
    int16   cwind;          /*  Congestion window                           */
    int16   ssthresh;       /*  Slow-start threshold                        */
    int32   rttseq;         /*  Sequence number being timed                 */
    int16   sndcnt;         /*  Number of unack'd seq numbers on send queue */
    int32   resent;         /*  Count of retransmitted bytes                */
    char    state;          /*  Current TCB state                           */
    char    send_ack;       /*  TRUE if an ACK is required to be sent       */
    char    retran;         /*  Retransmission flag                         */
    char    rtt_run;        /*  Retransmit timer flag                       */
    char    synack;         /*  Our SYN has been acked                      */
    clock_t rtt_time;       /*  Stored clock values for RTT                 */
    clock_t srtt;           /*  Smoothed Round Trip Timer, in 200hz ticks   */
    clock_t mdev;           /*  RTT deviation.  From Phil Karn's KA9Q       */
    clock_t wt;             /*  Timer for TIME_WAIT state                   */
    clock_t lastactive;     /*  */
    clock_t timer_d;        /*  Timer Duration.                             */
    clock_t timer_e;        /*  Expiration.  RTT or TIME_WAIT time or zero  */
} TCB;

#define	TCPDUPACKS	3

#define AGAIN   8   /* From KA9Q..  Thanks Phil..   */
#define LAGAIN  3
#define DGAIN   4
#define LDGAIN  2

#define abs(x)      (x>=0?x:-x)
#define min(x,y)    (x<=y?x:y)
#define max(x,y)    (x<y?y:x)

/* TCP connection states    */
#define TCLOSED     0   /* No connection.  Null, void, absent, .....        */
#define TLISTEN     1   /* Wait for remote request.  Not used here.         */
#define TSYN_SENT   2   /* Connect request sent.  Await matching request    */
#define TSYN_RECV   3   /* Wait for connection ACK.  (Listener only??)      */
#define TESTABLISH  4   /* Connection is established.  Handshake completed  */
#define TFIN_WAIT1  5   /* Await termination request or acknowledgement     */
#define TFIN_WAIT2  6   /* Await termination request.                       */
#define TCLOSE_WAIT 7   /* Await termination request from local user        */
#define TCLOSING    8   /* Await termination acknowledge from remote TCP    */
#define TLAST_ACK   9   /* Await acknowledgement of terminate request sent  */
#define TTIME_WAIT 10   /* Delay to ensure remote has received term' ACK    */

/* TCP and connection ERROR states. */
#define E_NORMAL        0   /* No error occured...                      */
#define E_OBUFFULL     -1   /* Output buffer is full                    */
#define E_NODATA       -2   /* No data available.                       */
#define E_EOF          -3   /* EOF from remote..						*/
#define E_RRESET       -4   /* RST received from remote.                */
#define E_UA           -5   /* RST.  Other end sent unacceptable pkt    */
#define E_NOMEM        -6   /* Something failed due to lack of memory   */
#define E_REFUSE       -7   /* Connection refused by remote             */
#define E_BADSYN       -8   /* A SYN was received in the window         */
#define E_BADHANDLE    -9   /* Bad connection handle used.              */
#define E_LISTEN       -10  /* The connection is in LISTEN state        */
#define E_NOCCB        -11  /* No free CCB's available                  */
#define E_NOCONNECTION -12  /* No connection matches this packet. (TCP) */
#define E_CONNECTFAIL  -13  /* Failure to connect to remote port. (TCP) */
#define E_BADCLOSE     -14  /* Invalid TCP_close() requested            */
#define E_USERTIMEOUT  -15  /* A user function timed out                */
#define E_CNTIMEOUT    -16  /* A the connection timed out               */
#define E_CANTRESOLVE  -17  /* Can't resolve the hostname               */
#define E_BADDNAME     -18  /* Domain name or Dotted Dec.  bad format   */
#define E_LOSTCARRIER  -19  /* The modem disconnected                   */
#define E_NOHOSTNAME   -20  /* Hostname does not exist                  */
#define E_DNSWORKLIMIT -21  /* Resolver Work limit reached              */
#define E_NONAMESERVER -22  /* No nameservers could be found for query  */
#define E_DNSBADFORMAT -23  /* Bad format of DS query                   */
#define E_UNREACHABLE  -24  /* Destination unreachable                  */
#define E_DNSNOADDR    -25  /* No address records exist for host        */
#define E_LASTERROR     25	/* ABS of last error code in this list      */


/* Input queue structures   */

typedef struct ndb {   /*  Network Data Block.  For data delivery   */
    char        *ptr;       /* Pointer to base of block. (For free();)  */
    char        *ndata;     /* Pointer to next data to deliver          */
    uint16      len;        /* Length of remaining data.                */
    struct ndb  *next;      /* Next NDB in chain or NULL               */
} NDB;

typedef struct ccb {    /* Connection Control Block.    */
    uint16      protocol;   /* TCP or UDP or ... 0 means CCB not in use */
    uint16      lport;      /* TCP client port.  (ie: At this machine)  */
    uint16      rport;      /* TCP server port.  (ie: remote machine)   */
    uint32      rhost;      /* TCP server IP addr. (ie: remote machine) */
    NDB         *ndq;       /* Start of stream data queue or NULL       */
    TCB         *tcb;       /* The TCB for a TCP connection only...     */
    int16       error;      /* Is the connection in error?              */
} CCB;

/*
 * "state" data for each active tcp conversation on the wire.  This is
 * basically a copy of the entire IP/TCP header from the last packet
 * we saw from the conversation together with a small identifier
 * the transmit & receive ends of the line use to locate saved header.
 */
struct cstate {
	struct cstate *cs_next;	/* next most recently used cstate (xmit only) */
	unsigned short		cs_hlen;	/* size of hdr (receive only) */
	unsigned char		cs_id;		/* connection # associated with this state */
	unsigned char		cs_filler;
	union {
		char 	csu_hdr[MAX_HDR];
		struct ip_header csu_ip;	/* ip/tcp hdr from most recent packet */
	} slcs_u;
};
#define cs_ip	slcs_u.csu_ip
#define cs_hdr	slcs_u.csu_hdr

 
/*typedef struct cstate {*/
/*	int cs_next; struct cstate *cs_next;	 next most recently used cstate (xmit only) */
/*	int cs_id;	 connection # associated with this state */
/*	struct ip_header cs_ip;	 ip/tcp hdr from most recent packet */
/*	struct tcp_header cs_tcp; tcp hdr from most recent packet */
/*};*/

/*
 *  Serial line state - we need one per line 
 *
 */

typedef struct slcompress {
	struct cstate 	*last_cs; /*struct cstate	*last_cs;	 most recently used tstate */
	octet			last_recv;	/* last rcvd conn. id */
	octet			last_xmit;	/* last sent conn. id */
	short			flags; 		/* was unsigned - Dan */
	struct cstate	*tstate[MAX_STATES];	/* xmit connection states */
	struct cstate	*rstate[MAX_STATES];	/* receive connection states */
};

typedef struct slip {
	DEV_LIST *bdev; /* backlink to interface */
	short		flags;		/* misc flags */
#define	SLF_ESC		0x01		/* next char is escaped */
#define SLF_DROP	0x02		/* drop this packet */
#define SLF_LINKED	0x04		/* interface is linked to device */
#define SLF_COMPRESS	0x08		/* turn on VJ compression */
#define SLF_AUTOCOMP	0x10		/* enable comp. on TCP_UNCOMP. frame */
#define SLF_COMPCID	0x20		/* enable CID compression */
#define SLF_USRMASK	(SLF_COMPRESS|SLF_AUTOCOMP|SLF_COMPCID)

	struct slcompress *comp;	/* states for VJ compression */
};



#define CNMAX		100		/* Maximum connections at any time.			*/
#define DFMAX		20    	/* Max number of reassembly buffers.		*/
#define MAX_QUERY	20		/* Max number of DNS queries.				*/

/* These are not always defined anywhere else,
 *  In particular not in MWC standard headers.
 */

#ifndef TRUE
#define TRUE    1
#endif
#ifndef FALSE
#define FALSE   0
#endif

/*  The elog[] array is a total count of various things that
 *  happen during a session.  The counts are usually, but
 *  not necessarily errors.  For example, a count is kept
 *  of the total number of packets created, and another of
 *  the total number deleted.  If these don't match at the
 *  end of the program, then some have been left hanging
 *  hanging around somewhere.  This could have implications
 *  for memory usage (ie: wastage).
 */

#define NS_SENT          0  /* Packet sent normally             */
#define EI_VERSION       1  /* Bad IP version                   */
#define EI_SUM           2  /* IP header checksum failure       */
#define EI_ADDRESS       3  /* Not addressed to us              */
#define EI_PROTOCOL      4  /* Unsupported protocol             */
#define EI_ICMPTYPE      5  /* Unsupported ICMP message type    */
#define EI_ICMPSUM       6  /* ICMP Checksum failure            */
#define EI_SNDPROTO      7  /* Sending unknown protocol         */
#define NI_REPLYPING     8  /* Normal ping response discarded   */
#define EU_UDPSUM        9  /* UDP header checksum failure      */
#define EI_NOLISTEN     10  /* ICMP no ping listener            */
#define TOT_CREATED     11  /* Count of packets created         */
#define TOT_DELETED     12  /* Count of packets deleted         */
#define NI_FRAGMENT     13  /* Number of fragments received     */
#define EU_NOPORT       14  /* No active UDP port               */
#define NT_QUEUEDOK     15  /* TCP input packet queued OK       */
#define EF_LISTFULL     16  /* Refrag descriptor list full      */
#define EA_NOMEMORY     17  /* Block creation fail.  No memory? */
#define EI_URNET        18  /* ICMP in, net unreachable         */
#define NOT_CREATED     19  /* Couldn't create packet           */
#define NF_ADDFRAG      20  /* Fragment was copied OK           */
#define EI_URHOST       21  /* ICMP in, host unreachable        */
#define EI_TTLZERO      22  /* Packet discarded due to TTL = 0  */
#define NU_QUEUEDOK     23  /* UDP input packet queued OK       */
#define ET_TCPSUM       24  /* TCP header checksum failure      */
#define ET_NOCONNECT    25  /* No connection for packet         */
#define EI_URPROTO      26  /* ICMP in, protocol unreachable    */
#define NT_SYNRECV      27  /* A SYN has been received          */
#define NT_PKTEMPTY     28  /* A packet with no data received   */
#define EI_URPORT       29  /* ICMP in, port unreachable        */
#define NT_RETRANSMIT   30  /* TCP retransmissions              */
#define ET_PQDROP       31  /* Closing, Pending packet dropped  */
#define CI_LOCALIN      32  /* Bytes in from provider           */
#define CI_LOCALOUT     33  /* Bytes out to provider            */
#define ET_LISTEN       34  /* Listen state (not possible!)     */
#define ET_RMRESET      35  /* Remote RESET the connection      */
#define CI_FOREIGNIN    36  /* Bytes in from other hosts        */
#define ET_NOSYNRST     37  /* Unsynch'd pkt has no SYN or RST  */
#define CI_FOREIGNOUT   38  /* Bytes out to other hosts         */
#define ET_NOACK        39  /* Packet has no ACK                */
#define ET_NODATASTATE  40  /* Data ignored due to TCP state    */
#define ET_DUPDATA      41  /* Duplicate data discarded         */
#define EI_TCPICMP      42  /* A tcp icmp message was delivered */
#define NT_CLOSING      43  /* Session is closing. Fin acked    */
#define EI_TTLTRANS     44  /* TTL exceeded in transit          */
#define EI_TTLFRAG      45  /* Frag TTL reassembled             */
#define EI_BADPARAM     46  /* Parameter problem                */
#define EI_QUENCH       47  /* Source quench message received   */
#define EI_ECHOREQUEST  48  /* Echo Request received            */
#define EI_ECHOREPLY    49  /* Echo reply received              */
#define EI_DFBEXCEEDED  50  /* Defrag buffer size exceeded      */
#define E_REASONS   51      /* Size of elog array               */


/*  The global configuration data structure.  Contains *ALL*
 *  relevant configurable values.  Defined in config.c
 */

typedef struct config {
    uint32  client_ip;          /*  IP address of client (local) machine    */
    uint32  provider;           /*  IP address of provider, or 0L           */
    uint16  ttl;                /*  Default TTL for normal packets          */
    uint16  ping_ttl;           /*  Default TTL for `ping'ing               */
    uint16  mtu;                /*  Default MTU (Maximum Transmission Unit) */
    uint16  mss;                /*  Default MSS (Maximum Segment Size)      */
    uint16  df_bufsize;         /*  Size of defragmentation buffer to use   */
    uint16  rcv_window;         /*  TCP receive window                      */
    uint16  def_rtt;            /*  Initial RTT time in ms                  */
    int16   time_wait_time;     /*  How long to wait in `TIME_WAIT' state   */
    int16   unreach_resp;       /*  Response to unreachable local ports     */
    int32   cn_time;            /*  Time connection was made                */
    int16   cd_valid;           /*  Is Modem CD a valid signal??            */
   	int16	tcp_protocol;		/*  What type of connection is this			*/
	void (*old_vec)(void);		/*  Old vector address */
	struct slip *slp;			/*  Slip structure for happiness */
} CONFIG;


/* Screen control defines, for functions in skio.c    */
#define SCRE_BOLD       1
#define SCRE_LIGHT      2
#define SCRE_ITALIC     4
#define SCRE_UNDERLINE  8
#define SCRE_OUTLINE   16
#define SCRE_SHADOW    32
#define SCRE_REVERSE  256   /* This is NOT a VDI attribute  */


/* Unreachable port responses   */
#define UP_IGNORE   0   /* Ignore the incoming packet (delete it)   */
#define UP_RESET    1   /* Send a TCP RST segment                   */
#define UP_ICMP     2   /* Send an ICMP message (The `Right' thing) */

#define	RTTCACHE 16     /* # of TCP round-trip-time cache entries */

struct tcp_rtt {
    uint32  addr;       /* Destination IP address */
    clock_t _srtt;      /* Most recent SRTT */
    clock_t _mdev;      /* Most recent mean deviation */
};

extern struct tcp_rtt Tcp_rtt[RTTCACHE];

/* FLagbox Flag definitions	*/
#define FL_do_resolve	0
#define FL_housekeep	1



/* Also declared here for convenience...    */
extern CONFIG cfg;
extern int16 bios_port, io_port;	/* bios_port is for DTR and CD	*/
extern long elog[E_REASONS];
extern char cdir[100];	/* Config directory	*/
extern struct slip *myslip;
extern struct slcompress *comp;
extern struct cstate mytstate[MAX_STATES];
extern struct cstate myrstate[MAX_STATES];
