/*
* Detailed Protocol Decoder for ICMP
*
* Christopher Wheeler(cwheeler@cac.washington.edu)
*
* 25 November 1992
*/
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include "ip_icmp.h"
#include "tcpview.h"
void detail_icmp(icmp, len)
register struct icmp *icmp;
u_short len;
{
u_long data_bytes;
u_short checksum;
#define PROTO_STR "ICMP: "
printf("%s----- ICMP packet -----\n", PROTO_STR);
hex(0, Phdr->caplen - Offset - 1); /* header line */
if ( Phdr->caplen - Offset < len ){
printf("%s[ICMP Packet truncated to %d bytes, should be %d]\n",
PROTO_STR, Phdr->caplen - Offset, len);
hex(0, Phdr->caplen - Offset - 1); /* second header line */
if ( Phdr->caplen - Offset < sizeof(struct icmp) ){
printf("%s[Unable to evaluate]\n", PROTO_STR);
hex(-1,-1); /* third header line */
return;
}
data_bytes = Phdr->caplen - Offset - ICMP_MINLEN;
}
else
data_bytes = len - ICMP_MINLEN;
printf("%s\n", PROTO_STR);
hex(-1,-1); /* blank */
hex(0,0); /* Type */
hex(1,1); /* Code */
hex(2,3); /* Checksum */
checksum = ntohs(icmp->icmp_cksum);
switch (icmp->icmp_type){
case ICMP_ECHOREPLY:
case ICMP_ECHO:
if ( icmp->icmp_type == ICMP_ECHOREPLY )
printf("%sType = %d (Echo Reply)\n", PROTO_STR, ICMP_ECHOREPLY);
else
printf("%sType = %d (Echo Request)\n", PROTO_STR, ICMP_ECHO);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIdentifier = %d\n", PROTO_STR, ntohs(icmp->icmp_id));
hex(4,5);
printf("%sSequence Number = %d\n", PROTO_STR, ntohs(icmp->icmp_seq));
hex(6,7);
printf("%s[%d bytes of optional data]\n", PROTO_STR, data_bytes);
hex(8, 8 + data_bytes - 1);
break;
case ICMP_UNREACH:
printf("%sType = %d (Destination Unreachable)\n", PROTO_STR,
ICMP_UNREACH);
switch (icmp->icmp_code){
case ICMP_UNREACH_NET:
printf("%sCode = %d (Network Unreachable)\n", PROTO_STR,
ICMP_UNREACH_NET);
break;
case ICMP_UNREACH_HOST:
printf("%sCode = %d (Host Unreachable)\n", PROTO_STR,
ICMP_UNREACH_HOST);
break;
case ICMP_UNREACH_PROTOCOL:
printf("%sCode = %d (Protocol Unreachable)\n", PROTO_STR,
ICMP_UNREACH_PROTOCOL);
break;
case ICMP_UNREACH_PORT:
printf("%sCode = %d (Port Unreachable)\n", PROTO_STR,
ICMP_UNREACH_PORT);
break;
case ICMP_UNREACH_NEEDFRAG:
printf("%sCode = %d (Fragmentation Needed and DF set)\n", PROTO_STR,
ICMP_UNREACH_NEEDFRAG);
break;
case ICMP_UNREACH_SRCFAIL:
printf("%sCode = %d (Source Route Failed)\n", PROTO_STR,
ICMP_UNREACH_SRCFAIL);
break;
default:
printf("%sCode = %s (Unknown Code)\n", PROTO_STR, icmp->icmp_code);
break;
}
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIP portion of originating message(description follows)\n\n",
PROTO_STR);
hex(8, 8 + data_bytes - 1);
hex(-1,-1);
Offset += ICMP_MINLEN;
detail_ip(&icmp->icmp_ip);
break;
case ICMP_SOURCEQUENCH:
printf("%sType = %d (Source Quench)\n", PROTO_STR, ICMP_SOURCEQUENCH);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIP portion of originating message(description follows)\n\n",
PROTO_STR);
hex(8, 8 + data_bytes - 1);
hex(-1,-1);
Offset += ICMP_MINLEN;
detail_ip(&icmp->icmp_ip);
break;
case ICMP_REDIRECT:
printf("%sType = %d (Redirect)\n", PROTO_STR, ICMP_REDIRECT);
switch(icmp->icmp_code){
case ICMP_REDIRECT_NET:
printf("%sCode = %d (Network)\n", PROTO_STR, ICMP_REDIRECT_NET);
break;
case ICMP_REDIRECT_HOST:
printf("%sCode = %d (Host)\n", PROTO_STR, ICMP_REDIRECT_HOST);
break;
case ICMP_REDIRECT_TOSNET:
printf("%sCode = %d (Type of Service and Network)\n", PROTO_STR,
ICMP_REDIRECT_TOSNET);
break;
case ICMP_REDIRECT_TOSHOST:
printf("%sCode = %d (Type of Service and Host)\n", PROTO_STR,
ICMP_REDIRECT_TOSHOST);
break;
default:
printf("%sCode = %d (Unknown)\n", PROTO_STR, icmp->icmp_code);
break;
}
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sGateway IP address = %s\n", PROTO_STR,
inet_ntoa(icmp->icmp_gwaddr));
hex(4,7);
printf("%sIP portion of originating message(description follows)\n\n",
PROTO_STR);
hex(8, 8 + data_bytes - 1);
hex(-1,-1);
Offset += ICMP_MINLEN;
detail_ip(&icmp->icmp_ip);
break;
case ICMP_DISC_AD:
{
struct icmp_ra_addr *ra;
u_long i, byte;
printf("%sType = %d (Discovery Advertisement)\n", PROTO_STR,
ICMP_DISC_AD);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sNumber of addresses = %d\n", PROTO_STR, icmp->icmp_num);
hex(4,4);
printf("%sAddress size = %d (32-bit words)\n", PROTO_STR,
icmp->icmp_size);
hex(5,5);
printf("%sLifetime = %d (sec)\n", PROTO_STR,
ntohs(icmp->icmp_lifetime));
hex(6,7);
printf("%s\n", PROTO_STR);
hex(-1,-1); /* blank line */
for ( ra = icmp->icmp_adv, i = 0;
i < icmp->icmp_num; ra++, i++ ){
if ( (u_long)ra + sizeof(struct icmp_ra_addr) >
(u_long)icmp + (Phdr->caplen - Offset) ){
printf("%s***** Entry Truncated *****\n", PROTO_STR);
hex(byte+8, Phdr->caplen - Offset - 1);
break;
}
byte = ICMP_MINLEN + (i * 8);
printf("%sRouter Address = %s\n", PROTO_STR, inet_ntoa(ra->addr));
hex(byte, byte+3);
printf("%sPreference Level = %lX\n", PROTO_STR, ntohl(ra->preference));
hex(byte+4, byte+7);
}
}
break;
case ICMP_DISC_SOLICIT:
printf("%sType = %d (Discovery Solicitation)\n", PROTO_STR,
ICMP_DISC_SOLICIT);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sReserved Data\n", PROTO_STR);
hex(4,7);
break;
case ICMP_TIMXCEED:
printf("%sType = %d (Time Exceeded)\n", PROTO_STR, ICMP_TIMXCEED);
switch(icmp->icmp_code){
case ICMP_TIMXCEED_INTRANS:
printf("%sCode = %d (TTL Count)\n", PROTO_STR, ICMP_TIMXCEED_INTRANS);
break;
case ICMP_TIMXCEED_REASS:
printf("%sCode = %d (Fragment reassembly time)\n", PROTO_STR,
ICMP_TIMXCEED_REASS);
break;
default:
printf("%sCode = %d (Unknown)\n", PROTO_STR, icmp->icmp_code);
break;
}
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIP portion of originating message(description follows)\n\n",
PROTO_STR);
hex(8, 8 + data_bytes - 1);
hex(-1,-1);
Offset += ICMP_MINLEN;
detail_ip(&icmp->icmp_ip);
break;
case ICMP_PARAMPROB:
printf("%sType = %d (Parameter Problem)\n", PROTO_STR, ICMP_PARAMPROB);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sPointer = %dX\n", PROTO_STR, (u_short)icmp->icmp_pptr);
hex(4,5);
printf("%sIP portion of originating message(description follows)\n\n",
PROTO_STR);
hex(8, 8 + data_bytes - 1);
hex(-1,-1);
Offset += ICMP_MINLEN;
detail_ip(&icmp->icmp_ip);
break;
case ICMP_TSTAMP:
case ICMP_TSTAMPREPLY:
if ( icmp->icmp_type == ICMP_TSTAMP )
printf("%sType = %d (Timestamp Request)\n", PROTO_STR, ICMP_TSTAMP);
else
printf("%sType = %d (Timestamp Reply)\n", PROTO_STR,
ICMP_TSTAMPREPLY);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIdentifier = %d\n", PROTO_STR, ntohs(icmp->icmp_id));
hex(4,5);
printf("%sSequence Number = %d\n", PROTO_STR, ntohs(icmp->icmp_seq));
hex(6,7);
printf("%sOriginate Timestamp = %d\n", PROTO_STR, ntohl(icmp->icmp_otime));
hex(8,11);
printf("%sReceive Timestamp = %d\n", PROTO_STR, ntohl(icmp->icmp_rtime));
hex(12,15);
printf("%sTransmit Timestamp = %d\n", PROTO_STR, ntohl(icmp->icmp_ttime));
hex(16,19);
break;
case ICMP_IREQ:
case ICMP_IREQREPLY:
if ( icmp->icmp_type == ICMP_IREQ )
printf("%sType = %d (Information Request)\n", PROTO_STR, ICMP_IREQ);
else
printf("%sType = %d (Information Reply)\n", PROTO_STR, ICMP_IREQREPLY);
printf("%sCode = %d (Should be 0)\n", PROTO_STR, icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sOther data\n", PROTO_STR);
hex(8, 8 + data_bytes - 1);
break;
case ICMP_MASKREQ:
case ICMP_MASKREPLY:
if ( icmp->icmp_type == ICMP_MASKREQ )
printf("%sType = %d (Address Mask Request)\n", PROTO_STR,
ICMP_MASKREQ);
else
printf("%sType = %d (Address Mask Reply)\n", PROTO_STR,
ICMP_MASKREPLY);
printf("%sCode = %d (Should be 0)\n", PROTO_STR,
icmp->icmp_code);
printf("%sChecksum = %lX\n", PROTO_STR, checksum);
printf("%sIdentifier = %d\n", PROTO_STR, ntohs(icmp->icmp_id));
hex(4,5);
printf("%sSequence Number = %d\n", PROTO_STR, ntohs(icmp->icmp_seq));
hex(6,7);
printf("%sAddress Mask = %s\n", PROTO_STR, inet_addr(icmp->icmp_mask));
hex(8,11);
break;
default:
printf("%sType = %d (Unknown)\n", PROTO_STR, icmp->icmp_type);
break;
}
printf("%s\n", PROTO_STR);
hex(-1,-1);
printf("%s----- End of ICMP packet -----\n", PROTO_STR);
hex(-1,-1);
}
syntax highlighted by Code2HTML, v. 0.9.1