/* NET/ROM header tracing routines
 * Copyright 1991 Phil Karn, KA9Q
 */
#include "global.h"
#include "mbuf.h"
#include "netrom.h"
#include "trace.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: nrdump.c,v 1.10 2000/05/09 16:48:28 brian Exp $";
#endif

#ifdef CTRACE
extern int SYSback;
#endif

/* Display NET/ROM network and transport headers */
void
netrom_dump (FILE *fp, struct mbuf **bpp, int check)
{
char src[AXALEN], dest[AXALEN];
char tmp[AXBUF];
char thdr[NR4MINHDR];
register int i;

	if (bpp == NULLBUFP || *bpp == NULLBUF)
		return;
	/* See if it is a routing broadcast */
#ifdef CTRACE
	if (use_ctrace)
	    traceprintf (fp, (SYSback == 4)? Awhite : Ablue);
#endif
	if (uchar (*(*bpp)->data) == NR3NODESIG) {
		(void) PULLCHAR (bpp);	/* Signature */
		(void) pullup (bpp, (unsigned char *) tmp, ALEN);
		tmp[ALEN] = '\0';
		traceprintf (fp, "NET/ROM Routing: %s\n", tmp);
		for (i = 0; i < NRDESTPERPACK; i++) {
			if (pullup (bpp, (unsigned char *) src, AXALEN) < AXALEN)
				break;
			traceprintf (fp, "        %12s", pax25 (tmp, src));
			(void) pullup (bpp, (unsigned char *) tmp, ALEN);
			tmp[ALEN] = '\0';
			traceprintf (fp, "%8s", tmp);
			(void) pullup (bpp, (unsigned char *) src, AXALEN);
			traceprintf (fp, "    %12s", pax25 (tmp, src));
			tmp[0] = (char) PULLCHAR (bpp);
			traceprintf (fp, "    %3u\n", uchar (tmp[0]));
		}
		return;
	}
	/* See if it is a routing poll - WG7J */
	if (uchar (*(*bpp)->data) == NR3POLLSIG) {
		(void) PULLCHAR (bpp);	/* Signature */
		(void) pullup (bpp, (unsigned char *) tmp, ALEN);
		tmp[ALEN] = '\0';
		traceprintf (fp, "NET/ROM Poll: %s\n", tmp);
		return;
	}
	/* Decode network layer */
	(void) pullup (bpp, (unsigned char *) src, AXALEN);
#ifdef CTRACE
	if (use_ctrace)
		traceprintf (fp, "NET/ROM: %s%s%s", Abold, pax25 (tmp, src) , Aboldoff);
	else
#endif	
	traceprintf (fp, "NET/ROM: %s", pax25 (tmp, src));

	(void) pullup (bpp, (unsigned char *) dest, AXALEN);
#ifdef CTRACE
	if (use_ctrace)
		traceprintf (fp, "->%s%s%s", Abold, pax25 (tmp, dest) , Aboldoff);
	else
#endif
	traceprintf (fp, "->%s", pax25 (tmp, dest));

	i = PULLCHAR (bpp);
	traceprintf (fp, " ttl %d\n", i);

	/* Read first five bytes of "transport" header */
	(void) pullup (bpp, (unsigned char *) thdr, NR4MINHDR);
	switch (thdr[4] & NR4OPCODE) {
		case NR4OPPID:	/* network PID extension */
			if (thdr[0] == NRPROTO_IP && thdr[1] == NRPROTO_IP) {
				ip_dump (fp, bpp, check);
				return;
			} else
				traceprintf (fp, "         protocol family %x, proto %x",
					  uchar (thdr[0]), uchar (thdr[1]));
			break;
		case NR4OPCONRQ:	/* Connect request */
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "         %sconn rqst%s: ckt %d/%d", Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]));
			else
#endif
			traceprintf (fp, "         conn rqst: ckt %d/%d", uchar (thdr[0]), uchar (thdr[1]));
			i = PULLCHAR (bpp);
			traceprintf (fp, " wnd %d", i);
			(void) pullup (bpp, (unsigned char *) src, AXALEN);
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " %s%s%s", Abold, pax25 (tmp, src) ,Aboldoff);
			else
#endif			
			traceprintf (fp, " %s", pax25 (tmp, src));
			(void) pullup (bpp, (unsigned char *) dest, AXALEN);
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "@%s%s%s", Abold, pax25 (tmp, dest) ,Aboldoff);
			else
#endif
			traceprintf (fp, "@%s", pax25 (tmp, dest));
			break;
		case NR4OPCONAK:	/* Connect acknowledgement */
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "         %sconn ack%s: ur ckt %d/%d my ckt %d/%d",
					Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]), uchar (thdr[2]),
					uchar (thdr[3]));
			else
#endif		
			traceprintf (fp, "         conn ack: ur ckt %d/%d my ckt %d/%d",
			  uchar (thdr[0]), uchar (thdr[1]), uchar (thdr[2]),
				     uchar (thdr[3]));
			i = PULLCHAR (bpp);
			traceprintf (fp, " wnd %d", i);
			break;
		case NR4OPDISRQ:	/* Disconnect request */
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "         %sdisc%s: ckt %d/%d",
					     Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]));
			else
#endif			
			traceprintf (fp, "         disc: ckt %d/%d",
				     uchar (thdr[0]), uchar (thdr[1]));
			break;
		case NR4OPDISAK:	/* Disconnect acknowledgement */
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "         %sdisc ack%s: ckt %d/%d",
					     Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]));
			else
#endif
			traceprintf (fp, "         disc ack: ckt %d/%d",
				     uchar (thdr[0]), uchar (thdr[1]));
			break;
		case NR4OPINFO:/* Information (data) */
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, "         %sinfo%s: ckt %d/%d",
					     Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]));
			else
#endif
			traceprintf (fp, "         info: ckt %d/%d",
				     uchar (thdr[0]), uchar (thdr[1]));
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " txseq %s%d%s rxseq %s%d%s",
					     Abold, uchar (thdr[2]), Aboldoff, Abold, uchar (thdr[3]), Aboldoff);
			else
#endif			
			traceprintf (fp, " txseq %d rxseq %d",
				     uchar (thdr[2]), uchar (thdr[3]));
			break;
		case NR4OPACK:	/* Information acknowledgement */
#ifdef CTRACE
			if (use_ctrace) {
				traceprintf (fp, "         %sinfo ack%s: ckt %d/%d",
					     Abold, Aboldoff, uchar (thdr[0]), uchar (thdr[1]));
				traceprintf (fp, " txseq %s%d%s rxseq %s%d%s",
					     Abold, uchar (thdr[2]), Aboldoff, Abold, uchar (thdr[3]), Aboldoff);
			} else {
#endif
			traceprintf (fp, "         info ack: ckt %d/%d",
				     uchar (thdr[0]), uchar (thdr[1]));
			traceprintf (fp, " txseq %d rxseq %d",
				     uchar (thdr[2]), uchar (thdr[3]));
#ifdef CTRACE
			}
#endif
			break;
		default:
			traceprintf (fp, "         unknown transport type %d",
				     thdr[4] & 0x0f);
			break;
	}
	if (thdr[4] & NR4CHOKE)
		traceprintf (fp, " CHOKE");
	if (thdr[4] & NR4NAK)
		traceprintf (fp, " NAK");
	if (thdr[4] & NR4MORE)
		traceprintf (fp, " MORE");
	traceprintf (fp, "\n");
}
