/*
*	udp.c
*/
#include "pcdefs.h"
#include "mbuf.h"
#include "protocol.h"
#include "data.h"
#include "config.h"
#include "funcdef.h"

/****************************************************************************/
/*  udpinterpret
*   take incoming UDP packets and make them 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 are (future).
*/
void _near _fastcall
udpinterpret(pkt, len)
union rawether _near *pkt;
u_int	len;
{
	u_int	i;
	struct udpport _far *p;
	u_char _far *cp;

	for (i = 0; i < NPORTS; i++) {
		p = (struct udpport _far *)portlist[i];
		if (!p)
			continue;
		if (p->type == SOCK_DGRAM &&
		    rawudp(pkt).u.dest == p->inport) {
			if (p->infree + len >= WINDOWSIZE - 1 -
			    sizeof(u_long) - 2 * sizeof(u_int)) {
				/* send icmp source quench */
				(void) neticmpsend(rawudp(pkt).i.ipsource, 4,
				    0, (u_char _near *)&rawudp(pkt).i,
				    sizeof(struct iph) + 8);
			} else {
				cp = &p->datain[p->infree];
				*((u_int _far *)cp)++ = len;
				*((u_int _far *)cp)++ = rawudp(pkt).u.source;
				*((u_long _far *)cp)++ = rawudp(pkt).i.ipsource;
				p->infree += len + sizeof(u_long)
				    + 2 * sizeof(u_int);
				(void) memcpy((u_char _far *)cp,
				    (u_char _far *)rawudp(pkt).data, len);
			}
			return;
		}
	}

	/*
	*	send a port unreachable
	*/
	if (rawudp(pkt).i.ipdest == Scon.myip)
		(void) neticmpsend(rawudp(pkt).i.ipsource, 3, 3,
		    (u_char _near *)&rawudp(pkt).i, sizeof(struct iph) + 8);
}
