/* ARP packet tracing routines
 * Copyright 1991 Phil Karn, KA9Q
 */
#include "global.h"
#include "mbuf.h"
#include "arp.h"
#include "trace.h"

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


void
arp_dump (fp, bpp)
FILE *fp;
struct mbuf **bpp;
{
struct arp arp;
struct arp_type *at;
int is_ip = 0;
char tmp[25];

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

#ifdef CTRACE
	if (use_ctrace)
		traceprintf (fp, "%sARP: len %d", Agreen, len_p (*bpp));
	else
#endif
	traceprintf (fp, "ARP: len %d", len_p (*bpp));
	if (ntoharp (&arp, bpp) == -1)	{
#ifdef CTRACE
		if (use_ctrace)
			traceprintf (fp, " %sbad packet%s%s\n", Aalert, Agreen, Aboldoff);
		else
#endif
		traceprintf (fp, " bad packet\n");
		return;
	}
	if (arp.hardware < NHWTYPES)
		at = &Arp_type[arp.hardware];
	else
		at = NULLATYPE;

	/* Print hardware type in Ascii if known, numerically if not */
	traceprintf (fp, " hwtype %s", smsg (Arptypes, NHWTYPES, arp.hardware));

	/* Print hardware length only if unknown type, or if it doesn't match
	 * the length in the known types table
	 */
	if(at == NULLATYPE || (int16) (int) arp.hwalen != at->hwalen)
		traceprintf (fp," hwlen %u", arp.hwalen);

	/* Check for most common case -- upper level protocol is IP */
	if (at != NULLATYPE && arp.protocol == at->iptype)	{
		traceprintf (fp, " prot IP");
		is_ip = 1;
	} else
		traceprintf (fp, " prot 0x%x prlen %u", arp.protocol, arp.pralen);

	switch (arp.opcode)	{
		case ARP_REQUEST:
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " op %sREQUEST%s", Abold, Aboldoff);
			else
#endif
			traceprintf (fp, " op REQUEST");
			break;
		case ARP_REPLY:
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " op %sREPLY%s", Abold, Aboldoff);
			else
#endif
			traceprintf (fp, " op REPLY");
			break;
		case REVARP_REQUEST:
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " op %sREVERSE REQUEST%s", Abold, Aboldoff);
			else
#endif
			traceprintf (fp, " op REVERSE REQUEST");
			break;
		case REVARP_REPLY:
#ifdef CTRACE
			if (use_ctrace)
				traceprintf (fp, " op %sREVERSE REPLY%s", Abold, Aboldoff);
			else
#endif
			traceprintf (fp, " op REVERSE REPLY");
			break;
		default:
			traceprintf (fp, " op %u",arp.opcode);
			break;
	}
	traceprintf (fp, "\nsender");
	if (is_ip) {
#ifdef CTRACE
		if (use_ctrace)
			traceprintf (fp, " IPaddr %s%s%s", Abold, inet_ntoa (arp.sprotaddr), Aboldoff);
		else
#endif
		traceprintf (fp, " IPaddr %s", inet_ntoa (arp.sprotaddr));
	}
#ifdef CTRACE
	if (use_ctrace)
		traceprintf (fp, " hwaddr %s%s%s\ntarget", Abold, (at) ? at->format (tmp, arp.shwaddr) : "??", Aboldoff);
	else		
#endif
	traceprintf (fp, " hwaddr %s\ntarget", (at) ? at->format (tmp, arp.shwaddr) : "??");
	if (is_ip) {
#ifdef CTRACE
		if (use_ctrace)
			traceprintf (fp, " IPaddr %s%s%s", Abold, inet_ntoa (arp.tprotaddr), Aboldoff);
		else
#endif
		traceprintf (fp, " IPaddr %s", inet_ntoa (arp.tprotaddr));
	}
#ifdef CTRACE
	if (use_ctrace)
		traceprintf (fp, " hwaddr %s%s%s\n", Abold, (at) ? at->format (tmp, arp.thwaddr) : "??", Aboldoff);
	else		
#endif
	traceprintf (fp, " hwaddr %s\n", (at) ? at->format (tmp, arp.thwaddr) : "??");
}

