/****************************************************************************
*
* (C) 2000 by BECK IPC GmbH
*
*  BECK IPC GmbH
*  Garbenheimerstr. 38
*  D-35578 Wetzlar
*
*  Phone : (49)-6441-905-240
*  Fax   : (49)-6441-905-245
*
* ---------------------------------------------------------------------------
* Module         : tcpip.c
*
* Function       : TCPIP API socket functions
*                  Use memory model large!!!!
*
* Author        : bartat
* Date          : 22.01.00
* Version       : V1.00
* ---------------------------------------------------------------------------
$Log: 
 10   IPC@CHIP  1.9         31.05.01 14:27:46    Christoph Stoidner 
 9    IPC@CHIP  1.8         31.05.01 09:18:00    Markus Bartat   bugfix snmp_get
 8    IPC@CHIP  1.7         29.05.01 16:04:20    Markus Bartat   added aPI call
      0x60 Get access to internal snmp variables
 7    IPC@CHIP  1.6         19.04.01 10:44:25    Markus Bartat   bugfix at
      tcp_connect: parameter error was overwritten by
      closesocket calls
 6    IPC@CHIP  1.5         14.03.01 16:56:21    Christoph Stoidner 
 5    IPC@CHIP  1.4         14.03.01 16:55:09    Christoph Stoidner convert
      datatypes to prevent compiler warnings
 4    IPC@CHIP  1.3         14.03.01 16:52:42    Christoph Stoidner 
 3    IPC@CHIP  1.2         08.03.01 15:30:17    Christoph Stoidner 
 2    IPC@CHIP  1.1         08.03.01 11:33:19    Ernest Schlösser Added a
      tcp_connect function to create a socket and connect to a server
 1    IPC@CHIP  1.0         14.02.01 16:09:59    Christoph Stoidner 
$

* History       :
*
*  Vx.yy                   Author  Changes
*
*  V1.00      22.01.00       mb    Create
*             28.01.00      mb     add calls setlinger and set reuse
*             06.05.00      mb     add ppp client API calls
*             26.06.00      mb     add ppp server API calls
*             14.07.00      mb     add reconfig, dhcp  and ip setting API calls
              18.07.00      mb     add TCPIP statistics
              24.08.00      mb     add PPP client API calls
              06.09.00      mb     add set and getsockopt calls
              15.09.00      mb     add ping api calls
              07.11.00      mb     add memory information call
              08.12.00      mb     add routing calls
              22.12.00      mb     add blocking mode call for sockets
*****************************************************************************/
#include <DOS.H>
#include <STDLIB.H>
#include "TCPIPAPI.H"
#include "TCPIP.H"



/*****************************************************************************
*
*	open a tcp connection
*
*	DestIPStr: destionation IP address format xxx.xxx.xxx.xxx
*	ClientPort: local port (0=random port)
*	HostPort: remote port
*	error: TCP/IP error
*
*
*	return: socket descriptor (-1 = error)
*/

int tcp_connect(char *DestIPStr, unsigned int ClientPort, unsigned int HostPort, int *error)
{
	struct sockaddr_in addr;
	unsigned long DestIPAddr;
	int sd; // socket descriptor
        int dummyerror;

	// open socket
	sd = opensocket(SOCK_STREAM,error);
	if (sd==-1 || *error!=0)
	{
		return -1;
	}

	addr.sin_family = PF_INET;
	addr.sin_port = htons(ClientPort);	// convert byte order
	addr.sin_addr.s_addr =  0;
	if (ClientPort!=0)
	{	// force client port
		bind(sd, (struct sockaddr *)&addr, error);
		if (*error!=0)
		{
                   closesocket(sd, &dummyerror);
			return -1;
		}
	}
	addr.sin_port = htons(HostPort);	// convert byte order

	// convert server IP address string to binary
	*error = inet_addr(DestIPStr,&DestIPAddr);
	if (*error!=0)
	{
             closesocket(sd, &dummyerror);
		return -1;
	}
	addr.sin_addr.s_addr = DestIPAddr;

	// establish a connection to the FTP server
	connect(sd, (struct sockaddr *) &addr, error);
	if (*error!=0)
	{
            closesocket(sd, &dummyerror);
		return -1;
	};

	*error = 0;
	return sd;

}	// ftp_connect()



/*************************************************************************/
//accept
/*************************************************************************/
int accept(int sd, struct sockaddr * addressPtr, int *error)
{

	  union  REGS  inregs;
	  union  REGS  outregs;

	  *error = 0;

	  inregs.h.ah     = API_ACCEPT;
	  inregs.x.bx     = sd;

	  inregs.x.dx     = FP_SEG(addressPtr);
	  inregs.x.si     = FP_OFF(addressPtr);

	  int86(TCPIPVECT,&inregs,&outregs);

	  if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
		  *error =  outregs.x.ax;
		  return API_ERROR;
	  }
	  //return socketdescriptor
	  *error = 0;
	  return outregs.x.ax;
}

/*************************************************************************/
//sleep
/*************************************************************************/
void api_sleep(unsigned int howlong)
{
	union  REGS  inregs;
	union  REGS  outregs;

	inregs.h.ah     = API_SLEEP;
	inregs.x.bx     = howlong;
	int86(TCPIPVECT,&inregs,&outregs);
}
/*************************************************************************/
//bind
/*************************************************************************/
int bind(int sd, struct sockaddr * addressPtr, int *error)
{

	union  REGS  inregs;
	union  REGS  outregs;

	*error = 0;
	inregs.h.ah     = API_BIND;
	inregs.x.bx     = sd;
	inregs.x.dx     = FP_SEG(addressPtr);
	inregs.x.si     = FP_OFF(addressPtr);
	int86(TCPIPVECT,&inregs,&outregs);

	if(outregs.x.dx == (unsigned int)API_ERROR)
	{
		 *error = outregs.x.ax;
	}
	return outregs.x.dx;
}
/*************************************************************************/
//connect
/*************************************************************************/
int connect(int sd, struct sockaddr * addressPtr, int *error)
{

	union  REGS  inregs;
	union  REGS  outregs;


	*error = 0;

	inregs.h.ah     = API_CONNECT;
	inregs.x.bx     = sd;
	inregs.x.dx     = FP_SEG(addressPtr);
	inregs.x.si     = FP_OFF(addressPtr);
	int86(TCPIPVECT,&inregs,&outregs);

	if(outregs.x.dx == (unsigned int)API_ERROR)
	{
		 *error = outregs.x.ax;

	}
	return outregs.x.dx;
}


/*************************************************************************/
//closesocket
/*************************************************************************/
int closesocket(int sd, int *error)
{

	union  REGS  inregs;
	union  REGS  outregs;

	inregs.h.ah = API_CLOSESOCKET;
	inregs.x.bx = sd;
	int86(TCPIPVECT,&inregs,&outregs);

	if(outregs.x.dx==(unsigned int)API_ERROR)
	{
	  *error = outregs.x.ax;
	}
	*error = 0;
	return outregs.x.dx;
}

/*************************************************************************/
//get waiting bytes
/*************************************************************************/
int GetWaitingBytes(int sd, int *error)
{
	union  REGS  inregs;
	union  REGS  outregs;

	inregs.h.ah      = API_GETRCV_BYTES;
	inregs.x.bx      = sd;
	int86(TCPIPVECT,&inregs,&outregs);

	if(outregs.x.dx==(unsigned int)API_ERROR)
	{
	  *error = outregs.x.ax;
	  return API_ERROR;
	}
	*error = 0;
	return outregs.x.ax;
}
/*************************************************************************/
//htons
/*************************************************************************/
unsigned int htons(unsigned int value)
{
	union  REGS  inregs;
	union  REGS  outregs;

	//set your listening port
	inregs.h.ah      = API_HTONS;
	inregs.x.bx      = value;
	int86(TCPIPVECT,&inregs,&outregs);

	return outregs.x.ax;
}

/*************************************************************************/
//listen
/*************************************************************************/
int listen(int sd,int backlog, int *error)
{
  union  REGS  inregs;
  union  REGS  outregs;

  inregs.h.ah      = API_LISTEN;
  inregs.x.bx      = sd;
  inregs.x.cx      = backlog;

  int86(TCPIPVECT,&inregs,&outregs);

  if(outregs.x.dx == (unsigned int)API_ERROR)
  {
	  *error = outregs.x.ax;
	  return API_ERROR;
  }
  *error = 0;
  return 0;
}
/*************************************************************************/
//inet_addr
/*************************************************************************/
int inet_addr(char * IPAddressStringPtr, unsigned long * IPAddress)
{
	union  REGS  inregs;
	union  REGS  outregs;
	struct SREGS sregs;

	inregs.h.ah      = API_INETADDR;
	inregs.x.bx      = FP_SEG(IPAddressStringPtr);
	inregs.x.si      = FP_OFF(IPAddressStringPtr);
	sregs.es         = FP_SEG(IPAddress);
	inregs.x.di      = FP_OFF(IPAddress);
	int86x(TCPIPVECT,&inregs,&outregs,&sregs);
	return outregs.x.dx;
}
/*************************************************************************/
//inet_to ascii
/*************************************************************************/
int InetToAscii(unsigned long * IPAddress, char * IPAddressStringPtr)
{

	  union  REGS  inregs;
	  union  REGS  outregs;
	  struct SREGS sregs;

	  inregs.h.ah     = API_INETTOASCII;
	  inregs.x.bx     = FP_SEG(IPAddress);
	  inregs.x.si     = FP_OFF(IPAddress);
	  sregs.es        = FP_SEG(IPAddressStringPtr);
	  inregs.x.di     = FP_OFF(IPAddressStringPtr);
	  int86x(TCPIPVECT,&inregs,&outregs,&sregs);
	  return 0;
}
/*************************************************************************/
//recvfrom
/*************************************************************************/
int recvfrom(int sd, char * bufptr, int bufLen, int flags,
				 unsigned long timeout,struct sockaddr * fromPtr, int *error)
{
	  int fromLen;
	  struct recv_params R;
	  union  REGS  inregs;
	  union  REGS  outregs;

	  //fill the struct recv_param R
	  fromLen          =   sizeof(struct sockaddr_in);
	  R.bufferPtr      =   bufptr;
	  R.bufferLength   =   bufLen;
	  R.flags          =   flags;
	  R.fromPtr        =   (struct sockaddr *)fromPtr;
	  R.fromlengthPtr  =   &fromLen;
	  R.timeout        =   timeout; /*milliseconds*/

	  //API
	  inregs.h.ah      = API_RECVFROM;
	  inregs.x.bx      = sd;
	  inregs.x.dx      = FP_SEG(&R);
	  inregs.x.si      = FP_OFF(&R);
	  int86(TCPIPVECT,&inregs,&outregs);

	  if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
			*error = outregs.x.ax;
			return API_ERROR;
	  }

	  *error = 0;
	  return outregs.x.ax;
}
/*************************************************************************/
//recv
/*************************************************************************/
int recv(int sd, char * bufptr, int bufLen, int flags, unsigned long timeout,
			int *error)
{

	  struct recv_params R;
	  union  REGS  inregs;
	  union  REGS  outregs;

	  //fill the struct recv_param R
	  R.bufferPtr      =   bufptr;
	  R.bufferLength   =   bufLen;
	  R.flags          =   flags;
	  R.timeout        =   timeout;
	  R.fromPtr        =   NULL;
	  R.fromlengthPtr  =   NULL;

	  inregs.h.ah      = API_RECV;
	  inregs.x.bx      = sd;
	  inregs.x.dx      = FP_SEG(&R);
	  inregs.x.si      = FP_OFF(&R);
	  int86(TCPIPVECT,&inregs,&outregs);

	  if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
		  *error = outregs.x.ax;
		  return API_ERROR;
	  }
	  *error = 0;
	  return outregs.x.ax;
}
/*************************************************************************/
//reset connection
/*************************************************************************/
int ResetConnection(int sd, int *error)
{
	  union  REGS  inregs;
	  union  REGS  outregs;

	  inregs.h.ah      = API_RESETCONNECTION;
	  inregs.x.bx      = sd;
	  int86(TCPIPVECT,&inregs,&outregs);
     if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
		  *error = outregs.x.ax;
		  return API_ERROR;
	  }
	  *error = 0;
	  return 0;
}
/*************************************************************************/
//sendto
/*************************************************************************/
int sendto(int sd, char * bufptr, int bufLen, int flags,
			  const struct sockaddr * toPtr, int *error)
{

	  int toLen;
	  struct send_params S;
	  union  REGS  inregs;
	  union  REGS  outregs;

	  //Init the struct send_param S for API-Call
	  toLen            = sizeof(struct sockaddr_in);
	  S.bufferPtr      = bufptr;
	  S.bufferLength   = bufLen;
	  S.flags          = flags;
	  S.toPtr          = (struct sockaddr *)toPtr;
	  S.tolengthPtr    = &toLen;

	  inregs.h.ah      = API_SENDTO;
	  inregs.x.bx      = sd;
	  inregs.x.dx      = FP_SEG(&S);
	  inregs.x.si      = FP_OFF(&S);
	  int86(TCPIPVECT,&inregs,&outregs);

	  if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
		 *error = outregs.x.ax;
		 return API_ERROR;
	  }
	  *error = 0;
	  return outregs.x.ax;
}

/*************************************************************************/
//send
/*************************************************************************/
int send(int sd, char * bufptr, int bufLen, int flags, int *error)
{
	  struct send_params S;
	  union  REGS  inregs;
	  union  REGS  outregs;

	  //fill the struct send_param S
	  S.bufferPtr      =   bufptr;
	  S.bufferLength   =   bufLen;
	  S.flags          =   flags;
	  S.toPtr          =   NULL;
	  S.tolengthPtr    =   NULL;

	  inregs.h.ah      = API_SEND;
	  inregs.x.bx      = sd;
	  inregs.x.dx      = FP_SEG(&S);
	  inregs.x.si      = FP_OFF(&S);
	  int86(TCPIPVECT,&inregs,&outregs);

	  if(outregs.x.dx == (unsigned int)API_ERROR)
	  {
		  *error = outregs.x.ax;
		  return API_ERROR;
	  }
	  *error = 0;
	  return outregs.x.ax;
}
/*************************************************************************/
//set linger time on close
/*************************************************************************/
int setlinger(int sd, int seconds, int *error)
{
	 union  REGS  inregs;
	 union  REGS  outregs;
	 inregs.h.ah = API_SETLINGER;
	 inregs.x.bx = sd;
	 inregs.x.cx = seconds;

	 int86(TCPIPVECT,&inregs,&outregs);

	 if(outregs.x.dx == (unsigned int)API_ERROR)
	 {
		  *error = outregs.x.ax;
		  return API_ERROR;
	 }
	 *error = 0;
	 return outregs.x.ax;
}
/*************************************************************************/
//set resuse option on a listening socket
/*************************************************************************/
int setreuse(int sd,int *error)
{
	 union  REGS  inregs;
	 union  REGS  outregs;
	 inregs.h.ah = API_SETREUSE;
	 inregs.x.bx = sd;

	 int86(TCPIPVECT,&inregs,&outregs);

	 if(outregs.x.dx == (unsigned int)API_ERROR)
	 {
		  *error = outregs.x.ax;
		  return API_ERROR;
	 }
	 *error = 0;
	 return outregs.x.ax;
}

/*************************************************************************/
//Set IP Type-Of-Service on a socket
/*************************************************************************/
int Set_IP_Type_Of_Service(int sd, unsigned char TOS, int *error)
{

   union  REGS  inregs;
	union  REGS  outregs;

   *error=0;
   inregs.h.ah = API_SETIPTOS;
   inregs.h.al = TOS;
   inregs.x.bx = sd;
	int86(TCPIPVECT,&inregs,&outregs);
   if((int)outregs.x.ax==-1)
   {
      *error = outregs.x.dx;
   }
   return  outregs.x.ax;

}

/*************************************************************************/
//get and set socket option
/*************************************************************************/

int setsockopt(int sd, SetSocketOption *sockoptptr, int *error)
{
  union  REGS  inregs;
	union  REGS  outregs;
   struct SREGS sregs;

   *error=0;
   inregs.h.ah = API_SETSOCKOPT;
   inregs.x.bx = sd;
   sregs.es    = FP_SEG(sockoptptr);
   inregs.x.di = FP_OFF(sockoptptr);
   int86x(TCPIPVECT,&inregs,&outregs,&sregs);

   if((int)outregs.x.dx==-1)
   {
      *error = outregs.x.ax;
   }
   return  outregs.x.dx;
}

int getsockopt(int sd, GetSocketOption *sockoptptr, int *error)
{
   union  REGS  inregs;
	union  REGS  outregs;
   struct SREGS sregs;

   *error=0;
   inregs.h.ah = API_GETSOCKOPT;
   inregs.x.bx = sd;
   sregs.es    = FP_SEG(sockoptptr);
   inregs.x.di = FP_OFF(sockoptptr);
   int86x(TCPIPVECT,&inregs,&outregs,&sregs);

   if((int)outregs.x.dx==-1)
   {
      *error = outregs.x.ax;
   }
   return  outregs.x.dx;
}


/*************************************************************************/
//Set blocking mode on a socket (default is blocking!!)
/*************************************************************************/
int Set_Blocking_Mode(int sd, unsigned char mode, int *error)
{

   union  REGS  inregs;
   union  REGS  outregs;

   *error=0;
   inregs.h.ah = API_SETBLOCKINGMODE;
   inregs.h.al = mode;
   inregs.x.bx = sd;
   int86(TCPIPVECT,&inregs,&outregs);
   if((int)outregs.x.dx==-1)
   {
      *error = outregs.x.ax;
   }
   return  outregs.x.dx;
}

/*************************************************************************/
//open socket
/*************************************************************************/
int opensocket(unsigned char type, int *error)
{

	union  REGS  inregs;
	union  REGS  outregs;

	inregs.h.ah = API_OPENSOCKET;
	inregs.h.al = type;


	int86(TCPIPVECT,&inregs,&outregs);

	if(outregs.x.dx == (unsigned int)API_ERROR)
	{
		*error = outregs.x.ax;
		return API_ERROR;
	}
	*error = 0;
	return outregs.x.ax;
}



/*************************************************************************/
//PPP client open
/*************************************************************************/
int PPP_Client_Open(PPPClient_Init * ptr, int *error)
{

   union  REGS  inregs;
	union  REGS  outregs;
   struct SREGS sregs;

   *error=0;

   inregs.h.ah      = PPPCLIENT_OPEN;
	sregs.es         = FP_SEG(ptr);
	inregs.x.di      = FP_OFF(ptr);
   int86x(TCPIPVECT,&inregs,&outregs,&sregs);

   if((int)outregs.x.dx==-1)
   {
      *error = outregs.x.ax;
   }

   return  outregs.x.dx;
}



/*************************************************************************/
//PPP client close
/*************************************************************************/
int PPP_Client_Close(int *error)
{

   union  REGS  inregs;
	union  REGS  outregs;

   *error=0;
   inregs.h.ah = PPPCLIENT_CLOSE;
	int86(TCPIPVECT,&inregs,&outregs);

   if((int)outregs.x.dx==-1)
   {
      *error = outregs.x.ax;
   }
   return  outregs.x.ax;
}

/*************************************************************************/
//PPP client get status
/*************************************************************************/
int PPP_Client_GetStatus(int *error)
{

   union  REGS  inregs;
	union  REGS  outregs;

   inregs.h.ah = PPPCLIENT_GET_STATUS;
	int86(TCPIPVECT,&inregs,&outregs);

   if((int)outregs.x.ax==-1)
   {
      *error = outregs.x.dx;
   }
   return  outregs.x.ax;
}


/*************************************************************************/
//PPP server installed
/*************************************************************************/

int PPP_Server_Installed(void)
{
   union  REGS  inregs;
	union  REGS  outregs;

   inregs.h.ah = PPPSERVER_INSTALLED;
	int86(TCPIPVECT,&inregs,&outregs);
   return  outregs.x.ax;
}


/*************************************************************************/
//PPP server suspend
/*************************************************************************/
int PPP_Server_Suspend(int timeoutsecs, int *error)
{

   union  REGS  inregs;
	union  REGS  outregs;

   *error=0;
   inregs.h.ah = PPPSERVER_SUSPEND;
   inregs.x.bx = timeoutsecs;
	int86(TCPIPVECT,&inregs,&outregs);
   if((int)outregs.x.ax==-1)
   {
      *error = outregs.x.dx;
   }
   return  outregs.x.ax;

}

/*************************************************************************/
//PPP server  activate
/*************************************************************************/
int PPP_Server_Activate(int timeoutsecs,int *error)
{
   union  REGS  inregs;
	union  REGS  outregs;

   *error=0;
   inregs.h.ah = PPPSERVER_ACTIVATE;
   inregs.x.bx = timeoutsecs;
	int86(TCPIPVECT,&inregs,&outregs);
   if((int)outregs.x.ax==-1)
   {
      *error = outregs.x.dx;
   }
   return  outregs.x.ax;
}


/*************************************************************************/
//PPP server  get config
/*************************************************************************/
int PPP_Server_Get_Cfg(PPP_IPCfg_Data *ptr , int *error)
{
   union  REGS  inregs;
	union  REGS  outregs;
   struct SREGS sregs;

   *error=0;

   inregs.h.ah = PPPSERVER_GET_CFG;
   sregs.es    = FP_SEG(ptr);
   inregs.x.di = FP_OFF(ptr);
   int86x(TCPIPVECT,&inregs,&outregs,&sregs);

   if((int)outregs.x.ax==-1)
   {
      *error = outregs.x.dx;
   }
   return  outregs.x.ax;
}



/*************************************************************************/
//PPP server, get status
/*************************************************************************/
int PPP_Server_GetStatus(void)
{

   union  REGS  inregs;
	union  REGS  outregs;


   inregs.h.ah = PPPSERVER_GET_STATUS;

	int86(TCPIPVECT,&inregs,&outregs);
   return  outregs.x.ax;
}


/*************************************************************************/
//Get installed servers and devices of the SC12
/*************************************************************************/
void Get_Installed_Servers(unsigned int * AX, unsigned int *DX)
{
  union  REGS  inregs;
  union  REGS  outregs;

  inregs.h.ah = GET_INSTALLED_SERVERS;
  int86(TCPIPVECT,&inregs,&outregs);
  *AX = outregs.x.ax;
  *DX = outregs.x.dx;
}



/*************************************************************************/
//Reconfigure ethernet interface
/*************************************************************************/
int Reconfigure_ethernet(void)
{
  union  REGS  inregs;
  union  REGS  outregs;
  inregs.h.ah = REINIT_ETHERNET;
  int86(TCPIPVECT,&inregs,&outregs);
  return outregs.x.ax;
}

/*************************************************************************/
//DHCP use   dhcp_use 0/1
/*************************************************************************/
int DHCP_use(unsigned char dhcp_use)
{
  union  REGS  inregs;
  union  REGS  outregs;
  inregs.h.ah = DHCP_USE;
  inregs.h.al = dhcp_use;
  int86(TCPIPVECT,&inregs,&outregs);
  return outregs.x.ax;
}

/*************************************************************************/
//DHCP Stat
/*************************************************************************/
void Get_DHCP_Status(unsigned int * dhcp_use, unsigned int *dhcp_stat)
{
  union  REGS  inregs;
  union  REGS  outregs;
  inregs.h.ah = DHCP_STAT;
  int86(TCPIPVECT,&inregs,&outregs);
  *dhcp_use = outregs.x.ax;
  *dhcp_stat = outregs.x.dx;
}


/*************************************************************************/
//Get IP of the ethernet interface
/*************************************************************************/
void Get_IPConfig(char *IP, char * Mask, char *Gateway)
{
  union  REGS  inregs;
  union  REGS  outregs;
  struct SREGS sregs;

  inregs.h.ah = 0x01;
  sregs.es    = FP_SEG(IP);
  inregs.x.dx = FP_OFF(IP);
  int86x(0xA0,&inregs,&outregs,&sregs);

  inregs.h.ah = 0x03;
  sregs.es    = FP_SEG(Mask);
  inregs.x.dx = FP_OFF(Mask);
  int86x(0xA0,&inregs,&outregs,&sregs);


  inregs.h.ah = 0x05;
  sregs.es    = FP_SEG(Gateway);
  inregs.x.dx = FP_OFF(Gateway);
  int86x(0xA0,&inregs,&outregs,&sregs);
}

/*************************************************************************/
//Set IP configuration,becomes valid after call of reconfigure Ethernet
/*************************************************************************/
void Set_IPConfig(char *IP, char * Mask, char *Gateway)
{
  union  REGS  inregs;
  union  REGS  outregs;
  struct SREGS sregs;

  inregs.h.ah = 0x02;
  sregs.es    = FP_SEG(IP);
  inregs.x.dx = FP_OFF(IP);
  int86x(0xA0,&inregs,&outregs,&sregs);

  inregs.h.ah = 0x04;
  sregs.es    = FP_SEG(Mask);
  inregs.x.dx = FP_OFF(Mask);
  int86x(0xA0,&inregs,&outregs,&sregs);

  inregs.h.ah = 0x06;
  sregs.es    = FP_SEG(Gateway);
  inregs.x.dx = FP_OFF(Gateway);
  int86x(0xA0,&inregs,&outregs,&sregs);
}

/*************************************************************************/
//return the address of TCPIP packet counter struct
/*************************************************************************/
void Get_TCPIP_Statistics(Packet_Count * * Packet_Count_Pointer)
{
  union  REGS  inregs;
  union  REGS  outregs;
  struct SREGS sregs;

  inregs.h.ah = TCPIP_STATISTICS;
  int86x(TCPIPVECT,&inregs,&outregs,&sregs);

  *Packet_Count_Pointer = (Packet_Count *)MK_FP(sregs.es,outregs.x.di);

}

/*************************************************************************/
//ping open
/*************************************************************************/
int Ping_Open(Ping * pingptr, int * errorcode)
{
  union  REGS  inregs;
  union  REGS  outregs;
  struct SREGS sregs;


  inregs.h.ah = PING_OPEN;
  sregs.es    = FP_SEG(pingptr);
  inregs.x.di = FP_OFF(pingptr);
  int86x(TCPIPVECT,&inregs,&outregs,&sregs);
  *errorcode=outregs.x.ax;
  return outregs.x.dx;
}


/*************************************************************************/
//ping close
/*************************************************************************/
int Ping_Close(int sd)
{
  union  REGS  inregs;
  union  REGS  outregs;

  inregs.h.ah = PING_CLOSE;
  inregs.x.bx = sd;
  int86(TCPIPVECT,&inregs,&outregs);
  return outregs.x.dx;
}
/*************************************************************************/
//ping statistics
/*************************************************************************/
int Ping_Statistics(Ping * pingptr)
{
  union  REGS  inregs;
  union  REGS  outregs;
  struct SREGS sregs;



  inregs.h.ah = PING_STATISTICS;
  sregs.es    = FP_SEG(pingptr);
  inregs.x.di = FP_OFF(pingptr);
  int86x(TCPIPVECT,&inregs,&outregs,&sregs);
  return outregs.x.dx;
}

/*************************************************************************/
//memory
/*************************************************************************/
void Get_TCPIP_Memory_Status(unsigned long * total, unsigned long * used)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = GET_MEMORY_INFO;
   sregs.es    = FP_SEG(total);
   inregs.x.di = FP_OFF(total);
   sregs.ds    = FP_SEG(used);
   inregs.x.si = FP_OFF(used);
   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
}

/*************************************************************************/
//Add gateway
/*************************************************************************/
int  AddDefaultGateway( int interface , unsigned long * Gateway, int * errorcode)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = ADD_DEFAULT_GATEWAY;
   inregs.x.bx = interface;
   sregs.es    = FP_SEG(Gateway);
   inregs.x.di = FP_OFF(Gateway);

   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
   *errorcode=outregs.x.ax;
   return outregs.x.dx;
}

/*************************************************************************/
//Delete gateway
/*************************************************************************/
int  DelDefaultGateway(unsigned long * Gateway, int * errorcode)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = DEL_DEFAULT_GATEWAY;
   sregs.es    = FP_SEG(Gateway);
   inregs.x.di = FP_OFF(Gateway);

   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
   *errorcode=outregs.x.ax;
   return outregs.x.dx;
}

/*************************************************************************/
//Get gateway
/*************************************************************************/
int  GetDefaultGateway(unsigned long * Gateway, int * errorcode)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = GET_DEFAULT_GATEWAY;
   sregs.es    = FP_SEG(Gateway);
   inregs.x.di = FP_OFF(Gateway);

   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
   *errorcode=outregs.x.ax;
   return outregs.x.dx;
}


/*************************************************************************/
//Add a static route
/*************************************************************************/
int  AddStaticRoute(int interface, Route_Entry * route, int * errorcode)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = ADD_STATIC_ROUTE;
   inregs.x.bx = interface;
   sregs.es    = FP_SEG(route);
   inregs.x.di = FP_OFF(route);

   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
   *errorcode=outregs.x.ax;
   return outregs.x.dx;
}


/*************************************************************************/
//Delete a static route
/*************************************************************************/
int  DelStaticRoute(int interface, Route_Entry * route, int * errorcode)
{
   union  REGS  inregs;
   union  REGS  outregs;
   struct SREGS sregs;

   inregs.h.ah = DEL_STATIC_ROUTE;
   inregs.x.bx = interface;
   sregs.es    = FP_SEG(route);
   inregs.x.di = FP_OFF(route);

   int86x(TCPIPVECT,&inregs,&outregs,&sregs);
   *errorcode=outregs.x.ax;
   return outregs.x.dx;
}





/*************************************************************************/
//end tcpip.c
/*************************************************************************/
