/*
*    Protocol structures for network communication
*
****************************************************************************
*                                                                          *
*      part of:                                                            *
*      TCP/IP kernel for NCSA Telnet                                       *
*      by Tim Krauskopf                                                    *
*                                                                          *
*      National Center for Supercomputing Applications                     *
*      152 Computing Applications Building                                 *
*      605 E. Springfield Ave.                                             *
*      Champaign, IL  61820                                                *
*                                                                          *
****************************************************************************
*
*  This file contains the structure definitions for each type of 
*  protocol that this program wishes to handle.  A companion file,
*  'protinit.c' initializes sample versions of each type of header, 
*  improving the efficiency of sending packets with constants in most
*  of the fields.
* 
*/
/************************************************************************/
/*  Ethernet frames
*      All Ethernet transmissions should use this Ethernet header which
*   denotes what type of packet is being sent.
*
*   The header is 14 bytes.  The first 6 bytes are the target's hardware
*   Ethernet address, the second 6 are the sender's hardware address and
*   the last two bytes are the packet type.  Some packet type definitions
*   are included here.
*
*   the two-byte packet type is byte-swapped, PC is lo-hi, Ether is hi-lo
*/
#include "netdef.h"

#define  EXNS  0x0006           /* probably need swapping */
#define  EIP   0x0008
#define  EARP  0x0608
#define  ERARP	0x3580			/* I guess this is RARP */
#define  ECHAOS  0x0408

struct ether {
	u_char	dest[DADDLEN];	/* where the packet is going */
	u_char	me[DADDLEN];	/* who am i to send this packet */
	u_int	type;		/* Ethernet packet type  */
};
typedef struct ether DLAYER;

/*************************************************************************/
/*  Dave Plummer's  Address Resolution Protocol (ARP) (RFC-826) and 
*   Finlayson, Mann, Mogul and Theimer's Reverse ARP packets.
*
*   Note that the 2 byte ints are not byte-swapped.  The protocols calls for
*   in-order bytes, and the PC is lo-hi ordered.
*   
*/

#define RARPR	0x0004          /*  RARP reply, from host */
#define RARPQ	0x0003		/*  RARP request */
#define ARPREP  0x0002          /*  reply */
#define ARPREQ  0x0001          /*  request */
#define ARPPRO	0x0800		/*  IP protocol */
#define HTYPE 	0x0001		/*  Ethernet hardware type */

struct arp {
	DLAYER	d; 		/* data link layer packet header */
	u_int	hrd;		/* hardware type, Ethernet = 1 */
	u_int	pro;		/* protocol type to resolve for */
	u_char	hln;		/* byte length of hardware addr = 6 for ETNET */
	u_char	pln;		/* byte length of protocol = 4 for IP */
	u_int	op;		/* opcode, request = 1, reply = 2, RARP = 3,4 */
	u_char	sha[DADDLEN];	/* sender hardware address */
	u_long	spa;		/* sender protocol address */
	u_char	tha[DADDLEN];	/* target hardware address */
	u_long	tpa;		/* target protocol address */
};
typedef struct arp ARPKT;

/***********************************************************************/
/*  ARP cache
*   Data structure for saving low-level information until needed
*/
struct acache {
	u_char	hrd[DADDLEN];	/* hardware address for this IP address */
	u_long	ip;		/* the IP # in question */
	u_long	tm;		/* time information */
#ifdef notdef
	u_char	gate;		/* is this a gateway? */
#endif
};

/***********************************************************************/
/*   Internet protocol
*
*/
struct iph {
	u_char	versionandhdrlen;	/* I prefer to OR them myself */
					/* each half is four bits */
	u_char	service;		/* type of service for IP */
	u_int	tlen;			/* total length of IP packet */
	u_int	ident;			/* these are all BYTE-SWAPPED! */
	u_int	frags;			/* combination of flags and value */
	u_char	ttl;    		/* time to live */
	u_char	protocol;		/* higher level protocol type */
	u_int	check;			/* header checksum, byte-swapped */
	u_long	ipsource;		/* IP addresses */
	u_long	ipdest;
};
typedef struct iph IPLAYER;

/*  
*  full IP packet, with data and ip header
*/

struct ip {
	DLAYER d;
	IPLAYER i;
	union {
		u_char	data[536]; /* recommended max, may include options */
		u_char	options[40];
	} x;
};
typedef struct ip IPKT;

#define PROTUDP		17
#define PROTTCP		6		/* standard protocol types for IP */
#define PROTICMP	1
/************************************************************************/
/* ICMP packet
*  all of them are of a similar form, some generic fields are spec'd here.
*/
struct icmph {
	u_char	type;		/* ICMP type field */
	u_char	code;		/* ICMP code field */
	u_int	check;          /* checksum */
	u_int	part1;		/* depends on type and code */
	u_int	part2;
};
typedef struct icmph ICMPLAYER;

#define	INMREQ	17	/* netmask request */
#define	INMREP	18	/* netmask reply */

struct icmp {
	DLAYER d;
	IPLAYER i;
	ICMPLAYER c;
	u_char	data[ICMPMAX];
};
typedef struct icmp ICMPKT;

/**************************************************************************/
/*  TCP protocol
*      define both headers required and create a data type for a typical
*      outgoing TCP packet (with IP header)
*   
*  Note:  So far, there is no way to handle IP options fields
*    which are associated with a TCP packet.  They are mutually exclusive
*    for both receiving and sending.  Support may be added later.
*
*   The tcph and iph structures can be included in many different types of
*   arbitrary data structures and will be the basis for generic send and
*   receive subroutines later.  For now, the packet structures are optimized 
*   for packets with no options fields.  (seems to be almost all of them from
*   what I've observed.
*/

struct tcph {
	u_int	source;		/* TCP port numbers, all byte-swapped */
	u_int	dest;
	u_long	seq;		/* sequence, ACK numbers */
	u_long	ack;
	u_char	hlen;		/* length of TCP header in 4 byte words */
	u_char	flags;		/* flag fields */
	u_int	window;		/* advertised window, byte-swapped */
	u_int	check;		/* TCP checksum of whole packet */
	u_int	urgent;		/* urgent pointer, when flag is set */
};
typedef struct tcph TCPLAYER;

/*
*  used for computing checksums in TCP
*/
struct pseudotcp {
	u_long	source;		/* IP #'s for source,dest */
	u_long	dest;
	u_char	z;		/* zero and protocol number */
	u_char	proto;
	u_int	tcplen;		/* byte-swapped length field */
};

struct tcp {
	DLAYER d;
	IPLAYER i;
	TCPLAYER t;
	union {
		u_char	options[40];	/* not very likely, except on SYN */
		u_char	data[TMAXSIZE];	/* largest TCP data we will use */
	} x;
};
typedef struct tcp TCPKT;

/* 
*  flag field definitions, first two bits undefined
*/
#define TURG	0x20
#define TACK	0x10
#define TPUSH	0x08
#define TRESET	0x04
#define TSYN	0x02
#define TFIN	0x01

/*************************************************************************/
/*  UDP
*   User Datagram Protocol
*   Each packet is an independent datagram, no sequencing information
*
*   UDP uses the identical checksum to TCP
*/
struct udph {
	u_int	source;		/* port numbers, all byte-swapped */
	u_int	dest;
	u_int	length;		/* length of packet, including hdr */
	u_int	check;		/* TCP checksum of whole packet */
};
typedef struct udph UDPLAYER;

struct udp {
	DLAYER d;
	IPLAYER i;
	UDPLAYER u;
	u_char	data[UMAXLEN];      /* largest UDP data we will use */
};
typedef struct udp UDPKT;

struct bpport {
	u_int	listen;		/* what port should this one listen to? */
	u_int	newdata;	/* have we read this packet yet? */
};

#define	SOCK_STREAM	1
#define	SOCK_DGRAM	2
struct port {
	u_char	type;
	u_char	flag;
	u_int	inport;		/* my port number in network order */
	u_int	outport;	/* dest port number in network byte order */
	u_long	fromip;		/* ip address to receive from */
	void	(far *anr)();	/* ANR routine to call upon data in */
	IPKT	outpkt;		/* pre-initialized as much as possible */
	u_char	stuff[2];	/* actually a lot more stuff here */
};

struct udpport {
	u_char	type;
	u_char	flag;
	u_int	inport;		/* my port number in network order */
	u_int	outport;	/* dest port number in network byte order */
	u_long	fromip;		/* ip address to receive from */
	void	(far *anr)();	/* ANR routine to call upon data in */
	UDPKT	outpkt;		/* pre-initialized as much as possible */
	u_char	datain[WINDOWSIZE];
	u_int	inbase;
	u_int	infree;
};

struct tcpport {
	u_char	type;
	u_char	flag;
	u_int	inport;		/* my port number in network order */
	u_int	outport;	/* dest port number in network byte order */
	u_long	fromip;		/* ip address to receive from */
	void	(far *anr)();	/* ANR routine to call upon data in */
	TCPKT	outpkt;		/* pre-initialized as much as possible */
	u_long	lasttime;	/* time of last transmission */
	u_long	inseq;
	u_long	inack;		/* don't need */
	u_long	outseq;
	u_long	outack;
	u_int	inbase;		/* start of data */
	u_int	infree;
	u_int	outbase;	/* don't need */
	u_int	outfree;
	u_char	datain[WINDOWSIZE];
	u_char	dataout[WINDOWSIZE];
	u_char	state;		/* connection state */
	u_int	outsize;	/* don't need */
	u_int	outwin;
	u_int	credit;		/* choked-down window for fast hosts */
	u_int	rto;		/* retrans timeout */
};
