/*
 * tcp_internal.h
 *
 * Derived from:
 *
 * Copyright (c) 1982, 1986 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of California at Berkeley. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 *
 *	@(#)tcp.h	7.3 (Berkeley) 12/7/87
 *
 * Modified for x-kernel v3.3
 * Modifications Copyright (c) 1996,1991  Arizona Board of Regents
 *
 * $Revision: 1.5 $
 * $Date: 1997/06/26 06:55:25 $
 */

/**************************************************************************

tcp_internal.h

**************************************************************************/
#ifndef tcp_internal_h
#define tcp_internal_h

#include "xkernel.h"
#include "sb.h"
#include "ip.h"
#include "tcp.h"
#include "tcp_port.h"

#ifndef ENDIAN
/*
 * Definitions for byte order,
 * according to byte significance from low address to high.
 */
#define LITTLE 1234		/* least-significant byte first (vax) */
#define BIG    4321		/* most-significant byte first */
#define PDP    3412		/* LSB first in word, MSW first in long (pdp) */
#if defined(vax) || defined(pmax)
#define ENDIAN LITTLE
#else
#define ENDIAN BIG		/* byte order on mc68000, tahoe, most others */
#endif
#endif ENDIAN

typedef u_long n_time;
#undef KPROF
#define PR_SLOWHZ 2
#define PR_FASTHZ 5
/* #define KERNEL */
#define BSD 43
#define TCP_COMPAT_42
#ifndef MIN
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
#endif
#ifndef MAX
#define MAX(A,B) ((A) >= (B) ? (A) : (B))
#endif

typedef struct {
    Semaphore s;
    int       waitCount;
} TcpSem;

struct tcpstate {
    u_int        flags;		/* see below */
    struct inpcb *inpcb;
    struct tcpcb *tcpcb;
    TcpSem       waiting;
    TcpSem       lock;
    Protl        hlpType;	/* for passively opened sessions */
    struct sb    *snd;
    int          rcv_space;	/* amount of space in the receiver's buffer */
    int          rcv_hiwat;	/* size of receiver's buffer */
    int          closed;
    int          tid;		/* TCP_TRACE */
};

#define TCPST_NBIO           0x0001	/* non-blocking i/o operations */
#define TCPST_OOBINLINE      0x0002	/* inline urgent data */
/* LSB 8/9/94 next three, not necesarily implemented! */
#define TCPST_PUSH_ALWAYS    0x0004	/* assume TCP-push after every xPush */
#define TCPST_RCV_ACK_ALWAYS 0x0008	/* assusme infinite receive buffer */
#define TCPST_KEEP_ALIVE     0x0010	/* keep connection alive */

#define sotoinpcb(S) (((struct tcpstate *)((S)->state))->inpcb)
#define sototcpst(S) ((struct tcpstate *)(S)->state)
#define tcpcbtoso(tp) (tp->t_inpcb->inp_session)
extern int tracetcpp;

/*
 * The arguments to usrreq are:
 *	(*protosw[].pr_usrreq)(up, req, m, nam, opt);
 * where up is a (struct socket *), req is one of these requests,
 * m is a optional mbuf chain containing a message,
 * nam is an optional mbuf chain containing an address,
 * and opt is a pointer to a socketopt structure or nil.
 * The protocol is responsible for disposal of the mbuf chain m,
 * the caller is responsible for any space held by nam and opt.
 * A non-zero return from usrreq gives an
 * UNIX error number which should be passed to higher level software.
 */
#define PRU_ATTACH     0	/* attach protocol to up */
#define PRU_DETACH     1	/* detach protocol from up */
#define PRU_BIND       2	/* bind socket to address */
#define PRU_LISTEN     3	/* listen for connection */
#define PRU_CONNECT    4	/* establish connection to peer */
#define PRU_ACCEPT     5	/* accept connection from peer */
#define PRU_DISCONNECT 6	/* disconnect from peer */
#define PRU_SHUTDOWN   7	/* won't send any more data */
#define PRU_RCVD       8	/* have taken data; more room now */
#define PRU_SEND       9	/* send this data */
#define PRU_ABORT      10	/* abort (fast DISCONNECT, DETATCH) */
#define PRU_CONTROL    11	/* control operations on protocol */
#define PRU_SENSE      12	/* return status into m */
#define PRU_RCVOOB     13	/* retrieve out of band data */
#define PRU_SENDOOB    14	/* send out of band data */
#define PRU_SOCKADDR   15	/* fetch socket's address */
#define PRU_PEERADDR   16	/* fetch peer's address */
#define PRU_CONNECT2   17	/* connect two sockets */
/* begin for protocols internal use */
#define PRU_FASTTIMO   18	/* 200ms timeout */
#define PRU_SLOWTIMO   19	/* 500ms timeout */
#define PRU_PROTORCV   20	/* receive from below */
#define PRU_PROTOSEND  21	/* send to below */

#define PRU_NREQ       21

extern char *prurequests[];

/*
 * Subset of the inpcb defined in /usr/include/netinet/in_pcb.h
 */
#ifdef XKMACHKERNEL
struct in_addr
{
    u_int s_addr;
};
#endif XKMACHKERNEL

struct inpcb {
    struct         inpcb *inp_next, *inp_prev;
    struct         inpcb *inp_head;
    caddr_t        inp_ppcb;		/* pointer to per-protocol pcb */
    struct in_addr inp_laddr, inp_raddr;
    u_short        inp_lport, inp_rport;
    Sessn          inp_session;
};

#define RCV 0
#define SND 1

#ifndef XKMACHKERNEL
#include <sys/errno.h>
#else
#define EINVAL       22		/* Invalid argument */
#define EWOULDBLOCK  35		/* Operation would block */
#define EOPNOTSUPP   45		/* Operation not supported on socket */
#define ECONNRESET   54
#define ENOBUFS      55
#define EISCONN      56		/* Socket is already connected */
#define ETIMEDOUT    60
#define ECONNREFUSED 61
#endif XKMACHKERNEL

typedef u_int tcp_seq;
/*
 * TCP header.
 * Per RFC 793, September, 1981.
 */
struct tcphdr {
    u_short th_sport;		/* source port */
    u_short th_dport;		/* destination port */
    tcp_seq th_seq;		/* sequence number */
    tcp_seq th_ack;		/* acknowledgement number */
#if ENDIAN == LITTLE
    u_char th_x2:4,		/* (unused) */
 	   th_off:4;		/* data offset */
#endif
#if ENDIAN == BIG
    u_char th_off:4,		/* data offset */
	   th_x2:4;		/* (unused) */
#endif
    u_char th_flags;
#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20
    u_short th_win;		/* window */
    u_short th_sum;		/* checksum */
    u_short th_urp;		/* urgent pointer */
};

#define TCPOPT_EOL             0
#define TCPOPT_NOP             1
#define TCPOPT_MAXSEG          2
#define TCPOLEN_MAXSEG         4
#define TCPOPT_WINDOW          3
#define TCPOLEN_WINDOW         3
#define TCPOPT_SACK_PERMITTED  4	/* Experimental */
#define TCPOLEN_SACK_PERMITTED 2
#define TCPOPT_SACK            5	/* Experimental */
#define TCPOPT_TIMESTAMP       8
#define TCPOLEN_TIMESTAMP      10
#define TCPOLEN_TSTAMP_APPA    (TCPOLEN_TIMESTAMP+2)	/* appendix A */

#define TCPOPT_TSTAMP_HDR \
    (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)

/*
 * Default maximum segment size for TCP.
 * With an IP MSS of 576, this is 536,
 * but 512 is probably more convenient.
 */
#ifdef lint
#define TCP_MSS	536
#else
#ifndef IP_MSS
#define IP_MSS  576
#endif
#define TCP_MSS MIN(512, IP_MSS - sizeof (struct tcpiphdr))
#endif

#define TCP_MAXWIN      65535   /* largest value for (unscaled) window */

#define TCP_MAX_WINSHIFT        14      /* maximum window shift */

/*
 * User-settable options (used with setsockopt).
 */
#define TCP_NODELAY 0x01	/* don't delay send to coalesce packets */
#define TCP_MAXSEG  0x02	/* set maximum segment size */


/*
 * X-Kernel defines
 */

/*====================  #8 10 lines added 070390 cliff ===================*/

#include "tcp_var.h"

#define TCP_TRACE               /* TCP_TRACE */ 
#define X_TRACE
#include "tcp_trace.h"          /* TCP_TRACE */

typedef struct pstate  {
    /* IPhost         myHost; */
    Map            activeMap;
    Map            passiveMap;
    void           *portstate;
    XkReturn       (*tcp_input)(Protl, Sessn, Msg *);
    int            (*tcp_output)(struct tcpcb *);
    struct tcpcb   *(*tcp_timers)(struct tcpcb *, int, void *);
    struct inpcb   tcb;
    struct tcpstat tcpstat;
    tcp_seq        tcp_iss;
    dt             *traceObj;
    int            vegasFlags;
    short          vegasExpNseg;
    short          vegasTopNseg;
    short          vegasBotNseg;
    short          delack;
    short          win_incr2;
/* LSB: for 4.4 */
    u_int          tcp_now;
    int            tcp_maxidle;
    int            reqScale;
    int            slowstart;
    /* int            connectionCnt; */
}  PSTATE;

typedef TCPport  PassiveId;

typedef struct {
    unsigned short localport;
    unsigned short remoteport;
    IPhost         remoteaddr;
} ActiveId;

typedef struct {
    IPpseudoHdr *h;
    Msg         *m;
} hdrStore_t;

#define FROM_ENABLE -1
#define TCPRCVWIN   (TCP_BUFFER_SPACE)

#undef bzero
#define bzero(str, len)  memset((void *)(str), (int)0, (size_t)(len))

extern char *tcpstates[];
/* extern long tcpIpProtocolNum; */

#ifdef __STDC__

/*
 * in_hacks.c
 */
int     in_pcballoc(Sessn , struct inpcb *);
void    in_pcbdisconnect(struct inpcb *);
void    in_pcbdetach(struct inpcb *);
bool    in_broadcast(struct in_addr);
u_short in_cksum(Msg *, u_short *, int len);

/*
 * tcp_subr.c
 */
struct tcpiphdr *tcp_template(struct tcpcb *);
struct tcpcb    *tcp_newtcpcb(PSTATE *, struct inpcb *);
struct tcpcb    *tcp_drop(struct tcpcb *, int errnum);
struct tcpcb    *tcp_destroy(struct tcpcb *);
void	        tcp_notify(struct inpcb *);
void	        tcp_quench(struct inpcb *);
void	        tcp_respond(Protl,  struct tcpcb *, struct tcphdr *,
			    IPpseudoHdr *, tcp_seq, tcp_seq, int);
 
/*
 * tcp_hdr.c
 */
void tcpHdrStore(void *, char *, long, void *);
void tcpOptionsStore(void *, char *, long, void *);
long tcpOptionsLoad(void *, char *, long, void *);
long tcpHdrLoad(void *, char *, long, void *);

/*
 * tcp_timer.c
 */
void         vtcp_fasttimo(Event, void *);
void         vtcp_slowtimo(Event, void *);
void         vtcp_canceltimers(struct tcpcb *);
struct tcpcb *vtcp_timers(struct tcpcb *, int, void *);
void         rtcp_fasttimo(Event, void *);
void         rtcp_slowtimo(Event, void *);
void         rtcp_canceltimers(struct tcpcb *);
struct tcpcb *rtcp_timers(struct tcpcb *, int, void *);

/*
 * tcp_x.c
 */
void  delete_tcpstate(struct tcpstate *);
void  sorwakeup(Sessn);
void  sowwakeup(Sessn);
void  soabort(Sessn);
void  socantsendmore(Sessn);
void  socantrcvmore(Sessn);
void  sohasoutofband(Sessn, u_int);
void  soisdisconnected(Sessn);
void  soisdisconnecting(Sessn);
void  soisconnected(Sessn);
void  soisconnecting(Sessn);
int   soreserve(Sessn, int, int);
Sessn ttcp_sonewconn(Protl, Protl, Protl, IPhost *, IPhost *, int, int);
Sessn rtcp_sonewconn(Protl, Protl, Protl, IPhost *, IPhost *, int, int);
Sessn vtcp_sonewconn(Protl, Protl, Protl, IPhost *, IPhost *, int, int);
void  tcpSemWait(TcpSem *);
void  tcpSemSignal(TcpSem *);
void  tcpSemInit(TcpSem *, int);
void  tcpSemVAll(TcpSem *);
void  tcpSemDestroy(TcpSem *);

/* 
 * tcp_output.c
 */
int  vtcp_output(struct tcpcb *);
void tcp_setpersist(struct tcpcb *);
int  ttcp_output(struct tcpcb *);
int  rtcp_output(struct tcpcb *);

/* 
 * tcp_usrreq.c
 */
int          tcp_attach(PSTATE *, Sessn);
int          tcp_usrreq(Sessn, int, Msg *, Msg *, int);
struct tcpcb *tcp_disconnect(struct tcpcb *);
struct tcpcb *tcp_usrclosed(struct tcpcb *);

/* 
 * tcp_input.c
 */
void     print_reass(struct tcpcb *, char *);
XkReturn vtcp_input(Protl, Sessn, Msg *);
int      tcp_mss(struct tcpcb *);
XkReturn vtcpPop(Sessn, Sessn, Msg *, void *);
int      tcp_reass(struct tcpcb *, struct tcphdr *, Sessn, Msg *, Msg *);
XkReturn ttcp_input(Protl, Sessn, Msg *);
XkReturn ttcpPop(Sessn, Sessn, Msg *, void *);
XkReturn rtcp_input(Protl, Sessn, Msg *);
XkReturn rtcpPop(Sessn, Sessn, Msg *, void *);

/* 
 * tcp_debug.c
 */
void tcp_trace(int, int, struct tcpcb *, struct tcpiphdr *, int);
char *tcpFlagStr(int);

/*
 * tcp_trace.c
 */
long tcpInitTime(void);
unsigned long tcpGetTime(void);
int  tcpSaveTrace(dt *, char *, int, struct tcpstat *);

#else

/*
 * in_hacks.c
 */
int     in_pcballoc();
void    in_pcbdisconnect();
void    in_pcbdetach();
bool    in_broadcast();
u_short in_cksum();

/*
 * tcp_subr.c
 */
struct tcpiphdr *tcp_template();
struct tcpcb    *tcp_newtcpcb();
struct tcpcb    *tcp_drop();
struct tcpcb    *tcp_destroy();
void            tcp_notify();
void            tcp_quench();
void            tcp_respond();
 
/*
 * tcp_hdr.c
 */
void tcpHdrStore();
void tcpOptionsStore();
long tcpOptionsLoad();
long tcpHdrLoad();

/*
 * tcp_timer.c
 */
void         vtcp_fasttimo();
void         vtcp_slowtimo();
void         vtcp_canceltimers();
struct tcpcb *vtcp_timers();
void         rtcp_fasttimo();
void         rtcp_slowtimo();
void         rtcp_canceltimers();
struct tcpcb *rtcp_timers();

/*
 * tcp_x.c
 */
/* void delete_tcpstate(); */
void  sorwakeup();
void  sowwakeup();
void  soabort();
void  socantsendmore();
void  socantrcvmore();
void  sohasoutofband();
void  soisdisconnected();
void  soisdisconnecting();
void  soisconnected();
void  soisconnecting();
int   soreserve();
Sessn ttcp_sonewconn();
Sessn rtcp_sonewconn();
Sessn vtcp_sonewconn();
void  tcpSemWait();
void  tcpSemSignal();
void  tcpSemInit();
void  tcpSemVAll();
void  tcpSemDestroy();

/* 
 * tcp_output.c
 */
int  vtcp_output();
void tcp_setpersist();
int  ttcp_output();
int  rtcp_output();

/* 
 * tcp_usrreq.c
 */
int          tcp_attach();
int          tcp_usrreq();
struct tcpcb *tcp_disconnect();
struct tcpcb *tcp_usrclosed();

/* 
 * tcp_input.c
 */
void     print_reass();
XkReturn vtcp_input();
int      tcp_mss();
XkReturn vtcpPop();
int      tcp_reass();
XkReturn ttcp_input();
XkReturn ttcpPop();
XkReturn rtcp_input();
XkReturn rtcpPop();

/* 
 * tcp_debug.c
 */
void tcp_trace();
char *tcpFlagStr();

/*
 * tcp_trace.c
 */
long tcpInitTime(); /* VENKAT */
long tcpGetTime(); /* VENKAT */
int tcpSaveTrace();

#endif __STDC__

#include "insque.h"

#endif
