/*****************************************************************************
* nettcp.c - Network Transport Control Protocol program file.
*
* Copyright (c) 1998 by Global Election Systems Inc. All rights reserved.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY (please don't use tabs!)
*
*(yyyy-mm-dd)
* 1998-02-02 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
* Original based on ka9q and BSD codes.
* 2001-05-18 Mads Christiansen <mads@mogi.dk>, Partner Voxtream
* Added support for running uC/IP in a single proces and on ethernet.
* Bugfix in resendTimeout, diffTime -> diffJTime!
* 2001-06-07 Robert Dickenson <odin@pnc.com.au>, Cognizant Pty Ltd.
* Quick fix to tcpInput for when OSSemCreate hadn't been called.
*
******************************************************************************
* NOTES
*
* MAXIMUM WINDOW
* We use a signed short int for the segment size adjustment (trimSeg()) to
* allow returning error codes. Thus our maximum segment size must be <=
* INT_MAX (i.e. 32767) rather than MAX_UINT. This is not a problem
* considering that we are using a PPP link over a serial link.
*
* HEADER CACHE
* The header values are all loaded in the header caches before being
* written to the outgoing segment so that a debugger can see the values
* of the header last sent.
******************************************************************************
* TO DO
*
* - Implement a SENDFIN flag in the tcb flags and use it in tcpOutput().
* - FINISH close!
*****************************************************************************/
#include "netconf.h"
#include <string.h>
#include "net.h"
#include "nettimer.h"
#include "netbuf.h"
#if MD5_SUPPORT > 0
#include "netrand.h"
#endif
#include "netmagic.h"
//#include "devio.h"
#include "netip.h"
#include "netiphdr.h"
#include "nettcp.h"
#include "nettcphd.h"
#include <stdio.h>
#include "netdebug.h"
#include "netos.h"
#pragma warning (push)
#pragma warning (disable: 4761) // integral size mismatch in argument; conversion supplied
#pragma warning (disable: 4018) // signed/unsigned mismatch
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
/* Configuration */
#define MAXTCP 12 /* Maximum TCP connections incl listeners. */
#define TCPTTL 64 /* Default time-to-live for TCP datagrams. */
#define OPTSPACE 5*4 /* TCP options space - must be a multiple of 4. */
#define NTCB 16 /* # TCB hash table headers */
#define MAXRETRANS 12 /* Maximum retransmissions. */
#define MAXKEEPTIMES 10 /* Maximum keep alive probe timeouts. */
#define MAXLISTEN 2 /* Maximum queued cloned listen connections. */
#define MAXFINWAIT2 600L /* Max time in seconds to wait for peer FIN. */
#define WRITESLEEP TICKSPERSEC /* Sleep time write waits for buffers (jiffies). */
#define STACK_SIZE NETSTACK /* Minimal stack. */
/*
* TCP connection control flag masks.
*/
#define FORCE 1 /* We owe the other end an ACK or window update */
#define CLONE 2 /* Server-type TCB, cloned on incoming SYN */
#define RETRAN 4 /* A retransmission has occurred */
#define ACTIVE 8 /* TCB created with an active open */
#define SYNACK 16 /* Our SYN has been acked */
#define KEEPALIVE 32 /* Send a keepalive probe */
/* Round trip timing parameters */
#define AGAIN 8 /* Average RTT gain = 1/8 */
#define DGAIN 4 /* Mean deviation gain = 1/4 */
#define MSL2 30 /* Guess at two maximum-segment lifetimes in seconds */
/* procInFlags return codes. */
#define ACKOK 0 /* OK to process segment. */
#define ACKDROP -1 /* Drop the segment. */
#define ACKRESET -2 /* Return segment as a reset. */
#define ACKCLOSE -3 /* Close the connection. */
/************************/
/*** LOCAL DATA TYPES ***/
/************************/
/*
* Combined TCP/IP headers with no options. Used to cached the headers.
*/
typedef struct TcpIPHdr_s {
IPHdr ipHdr; /* IP header - no options. */
TCPHdr tcpHdr; /* TCP header. tcpSeq, ack, off, & win
* are in host byte order.
*/
char options[OPTSPACE]; /* Cache for TCP options. */
} TCPIPHdr;
/*
* TCP session close reason codes.
*/
typedef enum {
NORMAL = 0, /* Normal close */
RESET = 1, /* Reset by other end */
TIMEOUT = 2, /* Excessive retransmissions */
NETWORK = 3 /* Network problem (ICMP message) */
} TCPReason;
/*
* TCP connection control block.
*/
typedef struct TCPCB_s {
struct TCPCB_s *prev; /* Linked list pointers for hash table */
struct TCPCB_s *next;
Connection conn; /* Connection struct for hash lookup. */
TCPState state; /* Connection state */
int freeOnClose; /* Flag set to free TCB on close. */
int closeReason; /* Reason for closing - TCPERR_ or 0 */
int traceLevel; /* Trace level this connection. */
/*
* Send sequence variables.
*/
struct {
u_int32_t una; /* First unacknowledged sequence number */
u_int32_t nxt; /* Next sequence num to be sent for the first time */
u_int32_t ptr; /* Working transmission pointer */
u_int16_t wnd; /* Other end's offered receive window */
u_int32_t wl1; /* Sequence number used for last window update */
u_int32_t wl2; /* Ack number used for last window update */
} snd;
u_int32_t iss; /* Initial send sequence number */
u_int16_t cwind; /* Congestion window */
u_int16_t ssthresh; /* Slow-start threshold */
u_int32_t resent; /* Count of bytes retransmitted */
/* Receive sequence variables */
struct {
u_int32_t nxt; /* Incoming sequence number expected next */
// u_int16_t wnd; /* Our offered receive window */
short wnd; /* Our offered receive window */
u_int16_t up; /* Receive urgent pointer */
} rcv;
u_int32_t irs; /* Initial receive sequence number */
u_int16_t mss; /* Maximum segment size */
u_int32_t rerecv; /* Count of duplicate bytes received */
int minFreeBufs; /* Minimum free buffers before we'll queue something. */
char backoff; /* Backoff interval */
char flags; /* Control flags */
int listenQOpen; /* Max queued listen connections. */
int listenQHead; /* Head of cloned TCB queue. */
int listenQTail; /* Tail of cloned TCB queue. */
struct TCPCB_s
*listenQ[MAXLISTEN +