#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "ip.h"
#include "slhc.h"
#include "trace.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: slhcdump.c,v 1.10 1996/09/04 01:34:13 root Exp $";
#endif

static int16 decodeint (struct mbuf ** bpp);


static int16
decodeint (struct mbuf **bpp)
{
char tmpbuf[2];

	(void) pullup (bpp, (unsigned char *) tmpbuf, 1);
	if (tmpbuf[0] == 0)
		(void) pullup (bpp, (unsigned char *) tmpbuf, 2);
	else {
		tmpbuf[1] = tmpbuf[0];
		tmpbuf[0] = 0;
	}
	return (get16 (tmpbuf));
}


void
vjcomp_dump (FILE *fp, struct mbuf **bpp, int unused OPTIONAL)
{
unsigned char changes;
char tmpbuf[2];

	if (bpp == NULLBUFP || *bpp == NULLBUF)
		return;

	/* Dump compressed TCP/IP header */
	changes = uchar(pullchar (bpp));
	traceprintf (fp, "\tchanges: 0x%02x", changes);
	if (changes & NEW_C) {
		(void) pullup (bpp, (unsigned char *) tmpbuf, 1);
		traceprintf (fp, "   connection: 0x%02x", uchar (tmpbuf[0]));
	}
	(void) pullup (bpp, (unsigned char *) tmpbuf, 2);
	traceprintf (fp, "   TCP checksum: 0x%04x", get16 (tmpbuf));

	if (changes & TCP_PUSH_BIT)
		traceprintf (fp, "   PUSH");
	traceprintf (fp, "\n");

	switch (changes & SPECIALS_MASK) {
		case SPECIAL_I:
			traceprintf (fp, "\tdelta ACK and delta SEQ implied by length of data\n");
			break;

		case SPECIAL_D:
			traceprintf (fp, "\tdelta SEQ implied by length of data\n");
			break;

		default:
			if (changes & NEW_U) {
				traceprintf (fp, "\tUrgent pointer: 0x%02x", decodeint (bpp));
			}
			if (changes & NEW_W)
				traceprintf (fp, "\tdelta WINDOW: 0x%02x", decodeint (bpp));
			if (changes & NEW_A)
				traceprintf (fp, "\tdelta ACK: 0x%02x", decodeint (bpp));
			if (changes & NEW_S)
				traceprintf (fp, "\tdelta SEQ: 0x%02x", decodeint (bpp));
			break;
	};
	if (changes & NEW_I) {
		traceprintf (fp, "\tdelta ID: 0x%02x\n", decodeint (bpp));
	} else {
		traceprintf (fp, "\tincrement ID\n");
	}
}


/* dump serial line IP packet; may have Van Jacobson TCP header compression */
void
sl_dump (FILE *fp, struct mbuf **bpp, int unused OPTIONAL)
{
struct mbuf *bp, *tbp;
unsigned char c;
int len;

	bp = *bpp;
	c = bp->data[0];
	if (c & SL_TYPE_COMPRESSED_TCP) {
		traceprintf (fp, "serial line VJ Compressed TCP: len %3u\n",
			     len_p (*bpp));
		vjcomp_dump (fp, bpp, 0);
	} else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
		traceprintf (fp, "serial line VJ Uncompressed TCP: len %3u\n",
			     len = len_p (bp));
		/* Get our own copy so we can mess with the data */
		if ((tbp = copy_p (bp, (int16) len)) == NULLBUF)
			return;

		traceprintf (fp, "\tconnection ID = %d\n",
			     uchar (tbp->data[9]));	/* FIX THIS! */
		/* Restore the bytes used with Uncompressed TCP */
		tbp->data[0] &= 0x4f;	/* FIX THIS! */
		tbp->data[9] = TCP_PTCL;	/* FIX THIS! */
		/* Dump contents as a regular IP packet */
		ip_dump (fp, &tbp, 1);
		free_p (tbp);
	} else {
		traceprintf (fp, "serial line IP: len: %3u\n", len_p (*bpp));
		ip_dump (fp, bpp, 1);
	}
}
