/****************************************************************************
** File: arp.c
**
** Author: Mike Borella
**
** Comments: Dump ARP / RARP header information
**
** $Id: arp.c,v 1.20 2001/10/19 15:24:56 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
**
*****************************************************************************/
#include "arp.h"
#include "ethertypes.h"
#define ARP_PADDING_SIZE 18 /* bytes to pad ARP to the min eth frame len */
/*
* ARP opcode map
*/
strmap_t arp_opcode_map[] =
{
{ ARP_OPCODE_REQUEST, "request" },
{ ARP_OPCODE_REPLY, "reply" },
{ RARP_OPCODE_REQUEST, "RARP request" },
{ ARP_OPCODE_REPLY, "RARP reply" },
{ 0, "" }
};
/*
* ARP hardware map
*/
strmap_t arp_hardware_map[] =
{
{ ARP_HWTYPE_ETHERNET, "Ethernet" },
{ ARP_HWTYPE_IEEE802, "IEEE 802" },
{ ARP_HWTYPE_IEEE1394, "IEEE 1394" },
{ 0, "" }
};
extern strmap_t ethertype_map[];
extern struct arg_t *my_args;
/*----------------------------------------------------------------------------
**
** dump_etherarp()
**
** Parse Ethernet-specifc parts of ARP messages
**
**----------------------------------------------------------------------------
*/
void dump_etherarp(packet_t *pkt)
{
ether_arp_t etharp;
/*
* Get the Ethernet section
*/
if (get_packet_bytes((u_int8_t *) ðarp, pkt, 20) == 0)
return;
/*
* Do minimal or not-so-minimal mode
*/
if (my_args->m)
{
display_minimal_ipv4((u_int8_t *) ðarp.target_protoaddr);
}
else
{
display("Sender Ether address", (u_int8_t *) ðarp.sender_hwaddr, 6,
DISP_HEXCOLONS);
display_ipv4("Sender IP address",
(u_int8_t *) ðarp.sender_protoaddr);
display("Target Ether address", (u_int8_t *) ðarp.target_hwaddr, 6,
DISP_HEXCOLONS);
display_ipv4("Target IP address",
(u_int8_t *) ðarp.target_protoaddr);
}
/*
* Some ARPs include Ethernet frame padding. Check for that. Note that we
* must allow ARP frames to be 1500 bytes. Some NICs seems to generate
* them as such. Strange but true. In any case, we set the apparent end
* of the packet to be at the place where we stop processing legit ARP
* bytes, and if padding is turned on, you'll see the rest of the bytes.
*/
if (!my_args->m)
{
int bytes;
bytes = get_packet_apparentbytesleft(pkt);
if (bytes > 0)
set_packet_apparentend(pkt, 0);
}
}
/*----------------------------------------------------------------------------
**
** dump_arp()
**
** Parse ARP header and dump fields
**
**----------------------------------------------------------------------------
*/
void dump_arp(packet_t *pkt)
{
arp_header_t arp;
/* Set the layer */
set_layer(LAYER_DATALINK);
/*
* Stats accounting
*/
stats_update(STATS_ARP);
/*
* Get the ARP fixed header
*/
if (get_packet_bytes((u_int8_t *) &arp, pkt, 8) == 0)
return;
/*
* Conversions
*/
arp.hwaddr_format = ntohs(arp.hwaddr_format);
arp.protoaddr_format = ntohs(arp.protoaddr_format);
arp.opcode = ntohs(arp.opcode);
/*
* Check for minimal mode first
*/
if (my_args->m)
{
display_minimal_string("| ARP ");
switch(arp.opcode)
{
case ARP_OPCODE_REQUEST:
case ARP_OPCODE_REPLY:
display_minimal_string(map2str(arp_opcode_map, arp.opcode));
display_minimal_string(" ");
break;
default:
break;
}
}
else
{
/*
* Banner announcement
*/
display_header_banner("ARP Header");
/*
* Dump hardware type
*/
display_strmap_hex("Hardware type", arp.hwaddr_format,
arp_hardware_map);
/*
* Dump protocol type
*/
display_strmap_hex("Protocol type", arp.protoaddr_format,
ethertype_map);
/*
* Dump hardware and protocol lengths
*/
display("Hardware length", (u_int8_t *) &arp.hwaddr_length, 1,
DISP_DEC);
display("Protocol length", (u_int8_t *) &arp.protoaddr_length, 1,
DISP_DEC);
/*
* Now do the opcode
*/
display_strmap("Opcode", arp.opcode, arp_opcode_map);
}
/*
* Check hardware type and layer 3 address format
*/
switch(arp.hwaddr_format)
{
case ARP_HWTYPE_ETHERNET:
switch(arp.protoaddr_format)
{
case ETHERTYPE_IP:
dump_etherarp(pkt);
break;
default:
break;
} /* inner switch */
default:
break;
} /* outer switch */
/* dump the hex buffer */
hexbuffer_flush();
}
syntax highlighted by Code2HTML, v. 0.9.1