#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "internet.h"
#include "ip.h"
#include "trace.h"
#include "rspf.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: rspfdump.c,v 1.9 1996/08/29 12:11:16 root Exp $";
#endif

#ifdef RSPF


/* Dump an RSPF packet */
void
rspf_dump (fp, bpp, source, dest, check)
FILE *fp;
struct mbuf **bpp;
uint32 source, dest;
int check;			/* If 0, bypass checksum verify */
{
union rspf rspf;
struct pseudo_header ph;
int16 csum;
int sync;

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

	traceprintf (fp, "RSPF: ");

	/* Compute checksum */
	ph.source = source;
	ph.dest = dest;
	ph.protocol = RSPF_PTCL;
	ph.length = len_p (*bpp);
	if ((csum = cksum (&ph, *bpp, ph.length)) == 0)
		check = 0;	/* No checksum error */

	(void) ntohrspf (&rspf, bpp);

	if (rspf.hdr.version != RSPF_VERSION)
		traceprintf (fp, "version %u ", rspf.hdr.version);
	switch (rspf.hdr.type) {
		case RSPF_FULLPKT:
			if (rspf.pkthdr.csum == 0)
				check = 0;
			traceprintf (fp, "type ROUTING UPDATE ");
			if (rspf.pkthdr.fragtot != 1)
				traceprintf (fp, "fragment %u frag total %u ", rspf.pkthdr.fragn,
					     rspf.pkthdr.fragtot);
			if (rspf.pkthdr.sync != 4)
				traceprintf (fp, "sync %u ", rspf.pkthdr.sync);
			traceprintf (fp, "nodes %u id %u", rspf.pkthdr.nodes, rspf.pkthdr.envid);
			if (check)
				traceprintf (fp, " CHECKSUM ERROR (%u)", csum);
			traceprintf (fp, "\n");
			if (rspf.pkthdr.sync != 0)
				sync = rspf.pkthdr.sync - 4;
			else
				sync = len_p (*bpp);
			if (sync % 5 != 0) {
				traceprintf (fp, "      %d bytes\n", sync);
				(void) pullup (bpp, (unsigned char *) 0, (int16) sync);
				sync = 0;
			}
			rspfnodedump (fp, bpp, sync / 5);
			break;
		case RSPF_RRH:
			if (rspf.rrh.csum == 0)
				check = 0;
			traceprintf (fp, "type RRH seq 0x%04x flags %d", rspf.rrh.seq, rspf.rrh.flags);
			if (check)
				traceprintf (fp, " CHECKSUM ERROR (%u)", csum);
			traceprintf (fp, "\n");
			break;
		default:
			traceprintf (fp, "Unknown packet type\n");
	}
}


void
rspfnodedump (fp, bpp, adjcnt)
FILE *fp;			/* uses tputs() if NULLFILE */
struct mbuf **bpp;		/* routing update without packet header */
int adjcnt;			/* number of links before first node header */
{
int c, links = 0;
char buf[128];
struct rspfnodeh nodeh;
struct rspflinkh linkh;

	*buf = '\0';
	for (;;) {
		if (*buf != '\0') {
			if (fp != NULLFILE)
				traceprintf (fp, "%s", buf);
			else
				tputs (buf);
			*buf = '\0';
		}
		if (len_p (*bpp) == 0)
			break;
		if (adjcnt) {
			if ((c = PULLCHAR (bpp)) == -1)
				break;
			sprintf (buf, "            %s/%u\n", inet_ntoa (pull32 (bpp)), c);
			adjcnt--;
			continue;
		}
		if (links) {
			if (ntohrspflink (&linkh, bpp) == -1)
				break;
			sprintf (buf, "      horizon %u ERP factor %u cost %u adjacencies %u\n",
			  linkh.horizon, linkh.erp, linkh.cost, linkh.adjn);
			adjcnt = linkh.adjn;
			links--;
			continue;
		}
		if (ntohrspfnode (&nodeh, bpp) == -1)
			break;
		sprintf (buf, "      Reporting Router: %s Seq %u Subseq %u links %u\n",
		    inet_ntoa (nodeh.addr), (int16) nodeh.seq, nodeh.subseq,
			 nodeh.links);
		links = nodeh.links;
	}
}

#endif /* RSPF */
