/* ARP packet tracing routines
 * Copyright 1991 Phil Karn, KA9Q
 */
#include "global.h"
#include "mbuf.h"
#include "arp.h"
#include "netuser.h"
#include "trace.h"
  
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 MONITOR
    if (Trace_compact_header)
    {
      /* it's different enough that we just do it here */
      /* except for the setup, that is... */
        if (ntoharp(&arp,bpp) == -1)
        {
            fprintf(fp, "bad packet\n");
            return;
        }
        if (arp.hardware < NHWTYPES)
            at = &Arp_type[arp.hardware];
        else
            at = NULLATYPE;
        if (at != NULLATYPE && arp.protocol == at->iptype)
            is_ip = 1;
        switch (arp.opcode)
        {
            case ARP_REQUEST:
            case REVARP_REQUEST:
                fprintf(fp, "REQ");
                break;
            case ARP_REPLY:
            case REVARP_REPLY:
                fprintf(fp, "REP");
                break;
            default:
                fprintf(fp, "%u", arp.opcode);
                break;
        }
        if (is_ip)
            fprintf(fp, " %s@", inet_ntoa(arp.sprotaddr));
        if (at)
            fprintf(fp, "%s->", at->format(tmp, arp.shwaddr));
        if (is_ip)
            fprintf(fp, "%s@", inet_ntoa(arp.tprotaddr));
        if (at)
            fprintf(fp, "%s", at->format(tmp, arp.thwaddr));
        fprintf(fp, "\n");
        return;
    }
#endif
  
    fprintf(fp,"ARP: len %d",len_p(*bpp));
    if(ntoharp(&arp,bpp) == -1){
        fprintf(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 */
    fprintf(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 || arp.hwalen != at->hwalen)
        fprintf(fp," hwlen %u",arp.hwalen);
  
    /* Check for most common case -- upper level protocol is IP */
    if(at != NULLATYPE && arp.protocol == at->iptype){
        fprintf(fp," prot IP");
        is_ip = 1;
    } else {
        fprintf(fp," prot 0x%x prlen %u",arp.protocol,arp.pralen);
    }
    switch(arp.opcode){
        case ARP_REQUEST:
            fprintf(fp," op REQUEST");
            break;
        case ARP_REPLY:
            fprintf(fp," op REPLY");
            break;
        case REVARP_REQUEST:
            fprintf(fp," op REVERSE REQUEST");
            break;
        case REVARP_REPLY:
            fprintf(fp," op REVERSE REPLY");
            break;
        default:
            fprintf(fp," op %u",arp.opcode);
            break;
    }
    fprintf(fp,"\n");
    fprintf(fp,"sender");
    if(is_ip)
        fprintf(fp," IPaddr %s",inet_ntoa(arp.sprotaddr));
    fprintf(fp," hwaddr %s\n",at->format(tmp,arp.shwaddr));
  
    fprintf(fp,"target");
    if(is_ip)
        fprintf(fp," IPaddr %s",inet_ntoa(arp.tprotaddr));
    fprintf(fp," hwaddr %s\n",at->format(tmp,arp.thwaddr));
}
