/* udp.c */

/*
 *  Includes
 */
#include <stdio.h>

#include "vtcpip.h"
#include "dfault.h"
#include "evtdef.h"
#include "hstdef.h"
#include "prodef.h"
#include "prodat.h"
#include "tcpdat.h"
#include "mapskt.h"
#include "bytprc.h"
#include "hdrchk.h"

/* 
 *  udpinterpret
 *
 *  Take an incoming UDP packet and make it available to the user level 
 *  routines.  Currently keeps the last packet coming in to a port.
 *
 *  Limitations :
 *
 *   Can only listen to one UDP port at a time, only saves the last packet
 *   received on that port.  Port numbers should be assigned like TCP ports.
 *
 */
int udpinterpret ( pkt, ulen )
register UDPKT *pkt;
register int ulen;
{
	register unsigned int hischeck,mycheck;

#ifdef	DEBUGOPTION
if(debug&0x44) {
	dmpfil("udpinp",(UDPKT *)pkt,sizeof(DLAYER)+sizeof(IPLAYER)+ulen);
}
#endif
	/*
	 *  did we want this data ?  If not, then let it go, no comment
	 *  If we want it, copy the relevent information into our structure
	 */
	if(intswap(pkt->u.dest)!=ulist.listen) 
		return(1);
	/*
	 *  first compute the checksum to see if it is a valid packet
	 */
	hischeck = pkt->u.check;
	pkt->u.check = 0;
	if (hischeck) {
		movebytes(tcps.source,pkt->i.ipsource,8);
		tcps.z = 0;
		tcps.proto = pkt->i.protocol;
		tcps.tcplen = intswap(ulen);
		mycheck = tcpcheck((char *)&tcps,
				(char *)&pkt->u,ulen);
		if(hischeck!=mycheck) {
			ntposterr(700);
			return(2);
		}
		pkt->u.check = hischeck;
	}
	ulen -= 8;
	if(ulen>UMAXLEN)
		ulen = UMAXLEN;
	movebytes(ulist.who,pkt->i.ipsource,4);
	movebytes(ulist.data,pkt->data,ulen);
	ulist.length = ulen;
	ulist.stale = 0;
	ntptuev(USERCLASS,UDPDATA,ulist.listen);
	return(0);
}

/*
 *  nturead ( buffer )
 *
 *  Get the data from the UDP buffer and transfer it into your buffer.
 *
 *  Returns the number of bytes transferred or -1 of none available
 *
 */
int nturead(buffer)
char *buffer;
{
	if(ulist.stale)
		return(-1);
	movebytes(buffer,ulist.data,ulist.length);
	ulist.stale = 1;
	return((int)ulist.length);
}

/*
 *  ntulisten ( port )
 *
 *  Specify which UDP port number to listen to --
 *  can only listen to one port at a time.
 *
 */
void ntulisten ( port )
int port;
{
	ulist.listen = port;
}

/*
 *  ntusend ( machine, port, retport, buffer, n )
 *
 *  Send some data out in a udp packet ( uses the preinitialized
 *  data in the port packet *ulist.udpout* )
 *
 *  Returns 0 on ok send, non-zero for an error
 *
 */
int ntusend(machine,port,retport,buffer,n)
register char *machine,*buffer;
unsigned int port,retport;
register int n;
{
	int ulen;
	char *pc;

	if(n>UMAXLEN)
		n = UMAXLEN;
	/*
	 *  make sure that we have the right dlayer address
	 */
	if(!comparen(machine,ulist.udpout.i.ipdest,4)) {
		pc = ntdlayer(machine);
		if(pc==NULL) 
			return(-2);
		movebytes(ulist.udpout.d.dest,pc,DADDLEN);
		movebytes(ulist.udpout.i.ipdest,machine,4);
		movebytes(ulist.tcps.dest,machine,4);
	}
	ulist.udpout.u.dest = intswap(port);
	ulist.udpout.u.source = intswap(retport);
	ulist.tcps.tcplen = ulist.udpout.u.length =
		intswap(n+sizeof(UDPLAYER));
	movebytes(ulist.udpout.data,buffer,n);
	/*
	 *  put in checksum
	 */
	ulist.udpout.u.check = 0;
	ulist.udpout.u.check =
		tcpcheck((char *)&ulist.tcps,
		(char *)&ulist.udpout.u,n+sizeof(UDPLAYER));
	/*
	 *   iplayer for send
	 */
	ulist.udpout.i.tlen = intswap(n+sizeof(IPLAYER)+sizeof(UDPLAYER));
	ulist.udpout.i.identity = intswap(nnipident++);
	ulist.udpout.i.check = 0;
	ulist.udpout.i.check = ipcheck((char *)&ulist.udpout.i,10);
	ulen = sizeof(DLAYER) + sizeof(IPLAYER) + sizeof(UDPLAYER) + n;
	/*
	 *  send it
	 */
#ifdef	DEBUGOPTION
if(debug&0x44) {
	dmpfil("udpout",&ulist.udpout,ulen);
}
#endif
	return(dlsend((DLAYER *)&ulist.udpout,ulen));
}
                                                                                                                                                                                                                                 