/**************************************************************************** ** 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(); }