/*
*	udp.c
*/
#include <string.h>
#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
udpinterpret(pkt, len)
union rawether _far *pkt;
unsigned	len;
{
	int	i;
	struct udpport *p;
	u_char *cp;

	for (i = 0; i < NPORTS; i++) {
		p = (struct udpport *)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_short)) {
				/* send icmp source quench */
				(void) neticmpsend(rawudp(pkt).i.ipsource, 4,
				    0, (u_char _far *)&rawudp(pkt).i,
				    sizeof(struct iph) + 8);
			} else {
				cp = &p->datain[p->infree];
				*(u_short *)cp = len;
				cp += sizeof (u_short);
				*(u_short *)cp = rawudp(pkt).u.source;
				cp += sizeof (u_short);
				*(u_long *)cp = rawudp(pkt).i.ipsource;
				cp += sizeof (u_long);
				p->infree += len + sizeof(u_long)
				    + 2 * sizeof(u_short);
				_fmemcpy(cp, rawudp(pkt).data, len);
			}
			return;
		}
	}

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