#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "netuser.h"
#include "icmp.h"
#include "trace.h"

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


/* Dump an ICMP header */
void
icmp_dump (fp, bpp, source, dest, check)
FILE *fp;
struct mbuf **bpp;
uint32 source OPTIONAL,dest OPTIONAL;
int check;		/* If 0, bypass checksum verify */
{
struct icmp icmp;
int16 csum;

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

	csum = cksum (NULLHEADER, *bpp, len_p (*bpp));
	(void) ntohicmp (&icmp, bpp);
	
#ifdef CTRACE	
	if (use_ctrace)
		traceprintf (fp, "%sICMP: type %s%s%s", Agreen, Abold, smsg(Icmptypes, ICMP_TYPES, uchar(icmp.type)), Aboldoff);
	else		
#endif
	traceprintf (fp, "ICMP: type %s", smsg(Icmptypes, ICMP_TYPES, uchar(icmp.type)));

	switch (uchar(icmp.type))	{
		case ICMP_DEST_UNREACH:
			traceprintf (fp, " code %s", smsg (Unreach, NUNREACH, uchar(icmp.code)));
			break;
		case ICMP_REDIRECT:
			traceprintf (fp, " code %s", smsg (Redirect, NREDIRECT, uchar(icmp.code)));
			traceprintf (fp, " new gateway %s", inet_ntoa (icmp.args.address));
			break;
		case ICMP_TIME_EXCEED:
			traceprintf (fp, " code %s", smsg (Exceed, NEXCEED, uchar(icmp.code)));
			break;
		case ICMP_PARAM_PROB:
			traceprintf (fp, " pointer %u", icmp.args.pointer);
			break;
		case ICMP_ECHO:
		case ICMP_ECHO_REPLY:
		case ICMP_INFO_RQST:
		case ICMP_INFO_REPLY:
		case ICMP_TIMESTAMP:
		case ICMP_TIME_REPLY:
			traceprintf (fp, " id %u seq %u", icmp.args.echo.id, icmp.args.echo.seq);
			break;
		default:
			break;
	}
	if (check && csum != 0)
		traceprintf (fp, " CHECKSUM ERROR (%u)", csum);

	traceprintf (fp, "\n");
	/* Dump the offending IP header, if any */
	switch (icmp.type)	{
		case ICMP_DEST_UNREACH:
		case ICMP_TIME_EXCEED:
		case ICMP_PARAM_PROB:
		case ICMP_QUENCH:
		case ICMP_REDIRECT:
			traceprintf (fp, "Returned ");
			ip_dump (fp, bpp, 0);
			break;
		default:
			break;
	}
}

