[Snort-users] ICMP Redirect Attack

Phil Wood cpw at ...440...
Wed May 9 15:31:20 EDT 2001


Folks,

I guess it's time for DecodeIP to come out of the closet.  I've attached
the perl script that generated ASCII headers (you are all familiar with
from reading the early RFC's) from tcpdump -x or any old hex.  It's a
good idea to have the hex start with the first byte of the IP header. %^)

If you do use it, I'd appreciate if you could send me any comments or changes.

Thanks,

On Tue, May 08, 2001 at 03:45:37PM -0500, Claude Bailey wrote:
> Could you send me a copy of the script used to print this?
> 
> Thanks.
> 
> -----Original Message-----
> From: Phil Wood [mailto:cpw at ...440...]
> Sent: Friday, April 06, 2001 4:59 PM
> To: Bob Van Cleef
> Cc: snort-users at lists.sourceforge.net
> Subject: Re: [Snort-users] ICMP Redirect Attack
> 
> 
> I took one of your packets and passed it through a script that
> breaks out the content of an icmp redirect:
> 
>               RFC791: INTERNET PROTOCOL, September 1981  
>    0                   1                   2                   3
>    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | VER=4 | IHL=5 | ROU | | | | | | Total Length = 131            |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Identification = 43336        | | | | Fragment Offset = 0     |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   |    TTL=49     | Protocol = 6  | Header Checksum = 65477       |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Source Address  = 192.86.6.23                                 |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Destination Address  = 212.223.69.26                          |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>         RFC793: TRANSMISSION CONTROL PROTOCOL, September 1981
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Source Port = 25              | Destination Port = 4827       |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Sequence Number = 569280001                                   |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Acknowledgment Number = 3478854381                            |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | OFF=5 | | | | | | | |A|P| | | |  Window = 4096                |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   | Checksum = 42403              | Urgent Pointer = 0            |
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>                                 Data
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>   :  32323020  6D657469  732E6D69  63726F75    : 220 metis.microu :
>   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> It shows that some box, 212.223.69.26, made a connection to your
> smtp (25) server.  It shows your server sent a perfectly valid response
> (beginning with 220 metis.microu ...) back to that box. 
> Some other box (17), which appears to be on the route to 26:
> 
>   ...
>   19  ser0.gbw1.ecore.net (212.63.129.46)  273.805 ms  302.637 ms  259.433
> ms
>   20  212.223.69.17 (212.223.69.17)  272.953 ms  264.606 ms  287.861 ms
>   21  212.223.69.26 (212.223.69.26)  292.220 ms  262.796 ms  260.749 ms
> 
> sent your smtp server the redirect.  Normally, redirects work between 
> routers on a shared media.  It is a way to say, "hey, I delievered your
> packet,
> but in the future you should send it to xyz which is my buddy on the same
> routing net).  However, you did send it to xyz (D4 DF 45 1A ==
> 212.223.69.26)!
> 
> So, how about this, the box is/was "promiscuous" for email destined for
> hosts
> on it's backside.  BTW, UDP packets (traceroute) go right through it.  Hmm,
> so do packets destined to smtp:
> 
>   Trying 212.223.69.26...
>   Connected to 212.223.69.26.
>   Escape character is '^]'.
>   220 mail.news-master.de ESMTP Lyris service ready
> 
> I wonder if someone sent me a redirect.  Should of had my ears on.
> 
> In a nutshell, it's junk, probably the result of some poor configuration.
> Maybe there are others out in snortland that have the rest of the story.
> 
> On Fri, Apr 06, 2001 at 01:34:56PM -0700, Bob Van Cleef wrote:
> > 
> > How do you read an ICMP redirect alert? I got a bunch of these... but
> > looking at the dumps left me sort of confused. ( A not untypical state. :)
> > 
> > [**] IDS135/icmp-redirect_host [**]
> > 04/05-22:14:29.448113 212.223.69.17 -> 192.86.6.23
> > ICMP TTL:244 TOS:0xC0 ID:43421 IpLen:20 DgmLen:179
> > Type:5  Code:1  REDIRECT
> > D4 DF 45 1A 45 00 00 83 A9 48 00 00 31 06 FF C5  ..E.E....H..1...
>     ^ xyz ^   ^ start of your packet
> > C0 56 06 17 D4 DF 45 1A 00 19 12 DB 21 EE 86 01  .V....E.....!...
> > CF 5B 1A ED 50 18 10 00 A5 A3 00 00 32 32 30 20  .[..P.......220
> > 6D 65 74 69 73 2E 6D 69 63 72 6F 75 6E 69 74 79  metis.microunity
> > 2E 63 6F 6D 20 45 53 4D 54 50 20 53 65 6E 64 6D  .com ESMTP Sendm
> > 61 69 6C 20 38 2E 38 2E 38 2F 38 2E 38 2E 38 3B  ail 8.8.8/8.8.8;
> > 20 54 68 75 2C 20 35 20 41 70 72 20 32 30 30 31   Thu, 5 Apr 2001
> > 20 32 32 3A 31 37 3A 35 39 20 2D 30 37 30 30 20   22:17:59 -0700
> > 28 50 44 54 29 0D 0A 01 51 80 00 01 00 02 A3 00  (PDT)...Q.......
> > 00 04 CE 0E 01 00 00 00 00 01 00                 ...........
> > 
> > 
> > 192.86.6.23 is metis.microunity.com, a mail server.  The contents
> > of this packet looks like something I would expect to be coming
> > from metis, not being sent to metis.
> > 
> > There were 13 alerts, the contents were all different, yet most
> > looked like something metis would be sending out... but not exactly.
> > 
> > [**] IDS135/icmp-redirect_host [**]
> > 04/05-16:47:53.006829 212.223.69.17 -> 192.86.6.23
> > ICMP TTL:244 TOS:0xC0 ID:55381 IpLen:20 DgmLen:157
> > Type:5  Code:1  REDIRECT
> > D4 DF 45 1A 45 00 00 6D 0C 5B 00 00 31 06 9C C9  ..E.E..m.[..1...
> > C0 56 06 17 D4 DF 45 1A 00 19 05 F1 01 C0 3E 5C  .V....E.......>\
> > FD 84 55 85 50 18 10 00 F6 3D 00 00 32 35 30 20  ..U.P....=..250
> > 6D 65 74 69 73 2E 6D 69 63 72 6F 75 6E 69 74 79  metis.microunity
> > 2E 63 6F 6D 20 48 65 6C 6C 6F 20 5B 32 31 32 2E  .com Hello [212.
> > 32 32 33 2E 36 39 2E 32 36 5D 2C 20 70 6C 65 61  223.69.26], plea
> > 73 65 64 20 74 6F 20 6D 65 65 74 20 79 6F 75 0D  sed to meet you.
> > 0A 31 36 3A 01 00 00 00 31 20 2D 30 37 30 30 20  .16:....1 -0700
> > 28 50 44 54 29                                   (PDT)
> > 
> > If metis was talking to 212.223.69.17, why would it think it was
> > talking to 212.223.69.26?
> > 
> > Bob
> > ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>  ><>
> > Bob Van Cleef, Member of Technical Staff         (408) 734-8100
> > MicroUnity Systems Engineering, Inc.         FAX (408) 734-8136
> > 376 Martin Ave., Santa Clara, CA 95050  vancleef at ...211...
> > 
> > 
> > _______________________________________________
> > Snort-users mailing list
> > Snort-users at lists.sourceforge.net
> > Go to this URL to change user options or unsubscribe:
> > http://lists.sourceforge.net/lists/listinfo/snort-users
> > Snort-users list archive:
> > http://www.geocrawler.com/redir-sf.php3?list=snort-users
> 
> -- 
> Phil Wood, cpw at ...440...
> 
> 
> _______________________________________________
> Snort-users mailing list
> Snort-users at lists.sourceforge.net
> Go to this URL to change user options or unsubscribe:
> http://lists.sourceforge.net/lists/listinfo/snort-users
> Snort-users list archive:
> http://www.geocrawler.com/redir-sf.php3?list=snort-users

-- 
Phil Wood, cpw at ...440...

-------------- next part --------------
#!/usr/bin/perl
#
#   Copyright (C) 2001 C. Philip Wood
#
#   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, 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 General Public License for more details.
# 
#   If you want a copy of the GNU General Public License, write to the
#   Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Requires: -x output from tcpdump as standard input
# Generates: RFC Compliant decode of IP/TCP, IP/UDP, and IP/ICMP packets.
# Try: ./DecodeIP -h to see the options
# Note: There is much more to do, such as decoding ip and tcp options.
#       Please send any updates to cpw at ...440...
#       Thanks, Phil

require 'getopts.pl';

BEGIN {

# IP Formats
$LBL1 = "   0                   1                   2                   3\n";
$LBL2 = "   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n"; 
$SEP0 = "  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n";
$IP0  = "              RFC791: INTERNET PROTOCOL, September 1981  \n";
$IP1  = "  | VER=%-2d| IHL=%-2d| %3s |%3s|%2s| Total Length = %-15d|\n";
$IP2  = "  | Identification = %-6d       |%5s| Fragment Offset = %-6d|\n";
$IP3  = "  |    TTL=%-3d    | Protocol = %-3d| Header Checksum = %-12d|\n";
$IP4  = "  | Source Address  = %-16s                            |\n";
$IP5  = "  | Destination Address  = %-16s                       |\n";
$OPT0 = "                               Options\n";
$OPT1 = "|     0x%s      ";
$IPOPT{0} = 'end';   #end of option list
$IPOPT{1} = 'nop';   #no operation
$IPOPT{7} = 'rr';   #record route
#                     |00000111| length | pointer|     route data    |
#                                                      mod 32 bits
$IPOPT{130} = 'secu'; #|10000010|00001011|SSS  SSS|CCC  CCC|HHH  HHH|  TCC   |
#                     SSS      SSS (16 bits)
#                     00000000 00000000 - Unclassified
#                     11110001 00110101 - Confidential
#                     01111000 10011010 - EFTO
#                     10111100 01001101 - MMMM
#                     01011110 00100110 - PROG
#                     10101111 00010011 - Restricted
#                     11010111 10001000 - Secret
#                     01101011 11000101 - Top Secret
#                     00110101 11100010 - (Reserved for future use)
#                     10011010 11110001 - (Reserved for future use)
#                     01001101 01111000 - (Reserved for future use)
#                     00100100 10111101 - (Reserved for future use)
#                     00010011 01011110 - (Reserved for future use)
#                     10001001 10101111 - (Reserved for future use)
#                     11000100 11010110 - (Reserved for future use)
#                     11100010 01101011 - (Reserved for future use)
#                     CCC      CCC (16 bits)
#                     HHH      HHH (16 bits)
#                     TCC          (24 bits)

$IPOPT{131} = 'lsrr';  # Loose Source and Record Route
#                      |10000011| length | pointer|     route data    |
#                      |<---------------  length  ------------------->|
#                                          pointer >= 4
$IPOPT{137} = 'ssrr';  # Strict Source and Record Route
#                      |10001001| length | pointer|     route data    |
$IPOPT{136} = 'sid';   # Stream Identifier
#                      |10001000|00000010|    Stream ID    |, length is 4.
$IPOPT{68}  = 'itim';  # Internet Timestamp
#                      |01000100| length | pointer|oflw|flg|
#                      +--------+--------+--------+--------+
#                      |         internet address          |
#                      +--------+--------+--------+--------+
#                      |             timestamp             |
#                      +--------+--------+--------+--------+
#                      |                 .                 |
#                      Maximum length is 40
#                      Pointer value points to slot for next timestamp
#                      Overflow (oflw) 4 bits is registers number of
#                        IP modules cannot register timestamps
#                      Flag (flg) 0 - time stamps only
#                                 1 - IP address followed by timestamp
#                                 3 - prespecified IP addreses
#                      timestamp is in milliseconds since midnight UT
#                                hi order bit indicates non-standard time
$IPOPTLEN{'end'} = 1;
$IPOPTLEN{'nop'} = 1;
$IPOPTLEN{'sid'} = 4;
$IPOPTLEN{'secu'} = 11;
$IPOPTLEN{'lsrr'} = 0; # 0 means variable found in next octet
$IPOPTLEN{'ssrr'} = 0;
$IPOPTLEN{'sid'} = 0;
$IPOPTLEN{'itim'} = 0;



# TCP Formats
$TCP0 = "        RFC793: TRANSMISSION CONTROL PROTOCOL, September 1981\n";
$TCP1 = "  | Source Port = %-5d           | Destination Port = %-5d      |\n";
$TCPS = "  | Sequence Number = %-15u                             |\n";
$TCPA = "  | Acknowledgment Number = %-15u                       |\n";
$TCPF = "  | OFF=%-2d|%s|  Window = %-5d               |\n";
$TCPC = "  | Checksum = %-5d              | Urgent Pointer = %-5d        |\n";
$DATA = "                                Data\n";

# UDP Formats
$UDP0 = "             RFC768: User Datagram Protocol, August 1980\n";
$UDP2 = "  | Length = %5d                | Checksum = %5d              |\n", 

# ICMP Formats
$ICMP0= "      RFC792: INTERNET CONTROL MESSAGE PROTOCOL, September 1981\n";
$ICMPX= "    %s %s\n";
$ICMP1= "  | Type = %-3d    | Code = %-3d    | Checksum = %-5d              |\n";
$ICMPI= "  | Identifier = %-5d            | Sequence Number = %-5d       |\n";
$ICMPD= "  |                             data                              |\n";
$ICMPU= "  | Unused = %8s                                         |\n";
$ICMPH= "  |                          header + 64 bits                     |\n";
$ICMPP= "  | Pointer = %3d | Unused = %6s                                  |\n";
$ICMPG= "  | Gateway = %16.16s                                    |\n";
$ICMPA= "  | Address Mask = %16s                              |\n";
$ICMPO= "  | Originate Timestamp: %-16d                      |\n";
$ICMPR= "  | Receive Timestamp: %-16d                   |\n";
$ICMPT= "  | Transmit Timestamp: %-16d                     |\n";
# Supported protocols
$IP = 1;
$TCP = 6;
$UDP = 17;
$ICMP = 1;

# ICMP Types
$icmpType[0] = "Echo Reply";
$icmpType[3] = "Destination Unreachable";
$icmpType[4] = "Source Quench";
$icmpType[5] = "Redirect (change route)";
$icmpType[8] = "Echo Request";
$icmpType[11] = "Time Exceeded";
$icmpType[12] = "Parameter Problem";
$icmpType[13] = "Timestamp Request";
$icmpType[14] = "Timestamp Reply";
$icmpType[15] = "Information Request";
$icmpType[16] = "Information Reply";
$icmpType[17] = "Address Mask Request";
$icmpType[18] = "Address Mask Reply";

# Codes for UNREACH
$unreachCode[0] = "Network Unreachable";
$unreachCode[1] = "Host Unreachable";
$unreachCode[2] = "Protocol Unreachable";
$unreachCode[3] = "Port Unreachable";
$unreachCode[4] = "Fragmentation Needed/DF set";
$unreachCode[5] = "Source Route failed";
$unreachCode[6] = "Network Unknown";
$unreachCode[7] = "Host Unknown";
$unreachCode[8] = "Host Isolated";
$unreachCode[9] = "Network Administratively Prohibited";
$unreachCode[10] = "Host Administratively Prohibited";
$unreachCode[11] = "Network Unreachable for TOS";
$unreachCode[12] = "Host Unreachable for TOS";
$unreachCode[13] = "Packet Filtered";
$unreachCode[14] = "Precedence Violation";
$unreachCode[15] = "Precedence Cutoff In Effect";

# Codes for REDIRECT
$redirCode[0] = "Redirect Net";
$redirCode[1] = "Redirect Host";
$redirCode[2] = "Redirect Net for TOS";
$redirCode[3] = "Redirect Host for TOS";

# Codes for TIME_EXCEEDED
$exceedCode[0] = "TTL count exceeded";
$exceedCode[1] = "Fragment Reass time exceeded";

$parameterCode[0] = "Unspecified";
$parameterCode[1] = "Missing Required Option";
$parameterCode[2] = "Bad Length";


# Unfinished business
$FIXME = 666;

# IP Header field values
# Type of Service
# Precedence
$PRE[0] = "ROU"; # Routine
$PRE[1] = "PRI"; # Priority
$PRE[2] = "IMM"; # Immediate
$PRE[3] = "FLS"; # Flash
$PRE[4] = "OVR"; # Flash Override
$PRE[5] = "ECP"; # CRITIC/ECP
$PRE[6] = "INC"; # Internetowrk Control
$PRE[7] = "NC "; # Network Control
#Delay, Throughput, and Reliability
$DTR[0] = " | | ";
$DTR[1] = " | |R"; # High Reliablity
$DTR[2] = " |T| "; # High Throughput
$DTR[3] = " |T|R";
$DTR[4] = "D| | "; # Low Delay
$DTR[5] = "D| |R";
$DTR[6] = "D|T| ";
$DTR[7] = "D|T|R";
# Reserved for Future Use
$FU[0] = " | ";
$FU[1] = " |X";
$FU[2] = "X| ";
$FU[3] = "X|X";
# Control Flags
$FLAGS[0] = " | | ";
$FLAGS[1] = " | |M"; # More Fragments
$FLAGS[2] = " |D| "; # Don't Fragment
$FLAGS[3] = " |D|M";
$FLAGS[4] = "X| | "; # Reserved, must be zero!
$FLAGS[5] = "X| |M";
$FLAGS[6] = "X|D| "; 
$FLAGS[7] = "X|D|M";
# Hex conversion table
$HX{'0'} = 0;
$HX{'1'} = 1;
$HX{'2'} = 2;
$HX{'3'} = 3;
$HX{'4'} = 4;
$HX{'5'} = 5;
$HX{'6'} = 6;
$HX{'7'} = 7;
$HX{'8'} = 8;
$HX{'9'} = 9;
$HX{'a'} = 10;
$HX{'A'} = 10;
$HX{'b'} = 11;
$HX{'B'} = 11;
$HX{'c'} = 12;
$HX{'C'} = 12;
$HX{'d'} = 13;
$HX{'D'} = 13;
$HX{'e'} = 14;
$HX{'E'} = 14;
$HX{'f'} = 15;
$HX{'F'} = 15;
$Char{'00'} = ' ';
$Char{'01'} = ' ';
$Char{'02'} = ' ';
$Char{'03'} = ' ';
$Char{'04'} = ' ';
$Char{'05'} = ' ';
$Char{'06'} = ' ';
$Char{'07'} = ' ';
$Char{'08'} = ' ';
$Char{'09'} = ' ';
$Char{'0a'} = ' ';
$Char{'0A'} = ' ';
$Char{'0b'} = ' ';
$Char{'0B'} = ' ';
$Char{'0c'} = ' ';
$Char{'0C'} = ' ';
$Char{'0d'} = ' ';
$Char{'0D'} = ' ';
$Char{'0e'} = ' ';
$Char{'0E'} = ' ';
$Char{'0f'} = ' ';
$Char{'0F'} = ' ';
$Char{'10'} = ' ';
$Char{'11'} = ' ';
$Char{'12'} = ' ';
$Char{'13'} = ' ';
$Char{'14'} = ' ';
$Char{'15'} = ' ';
$Char{'16'} = ' ';
$Char{'17'} = ' ';
$Char{'18'} = ' ';
$Char{'19'} = ' ';
$Char{'1a'} = ' ';
$Char{'1A'} = ' ';
$Char{'1b'} = ' ';
$Char{'1B'} = ' ';
$Char{'1c'} = ' ';
$Char{'1C'} = ' ';
$Char{'1d'} = ' ';
$Char{'1D'} = ' ';
$Char{'1e'} = ' ';
$Char{'1E'} = ' ';
$Char{'1f'} = ' ';
$Char{'1F'} = ' ';
$Char{'20'} = ' ';
$Char{'21'} = '!';
$Char{'22'} = '"';
$Char{'23'} = '#';
$Char{'24'} = '$';
$Char{'25'} = '%';
$Char{'26'} = '&';
$Char{'27'} = '\'';
$Char{'28'} = '(';
$Char{'29'} = ')';
$Char{'2a'} = '*';
$Char{'2A'} = '*';
$Char{'2b'} = '+';
$Char{'2B'} = '+';
$Char{'2c'} = ',';
$Char{'2C'} = ',';
$Char{'2d'} = '-';
$Char{'2D'} = '-';
$Char{'2e'} = '.';
$Char{'2E'} = '.';
$Char{'2f'} = '/';
$Char{'2F'} = '/';
$Char{'30'} = '0';
$Char{'31'} = '1';
$Char{'32'} = '2';
$Char{'33'} = '3';
$Char{'34'} = '4';
$Char{'35'} = '5';
$Char{'36'} = '6';
$Char{'37'} = '7';
$Char{'38'} = '8';
$Char{'39'} = '9';
$Char{'3a'} = ':';
$Char{'3A'} = ':';
$Char{'3b'} = ';';
$Char{'3B'} = ';';
$Char{'3c'} = '<';
$Char{'3C'} = '<';
$Char{'3d'} = '=';
$Char{'3D'} = '=';
$Char{'3e'} = '>';
$Char{'3E'} = '>';
$Char{'3f'} = '?';
$Char{'3F'} = '?';
$Char{'40'} = '@';
$Char{'41'} = 'A';
$Char{'42'} = 'B';
$Char{'43'} = 'C';
$Char{'44'} = 'D';
$Char{'45'} = 'E';
$Char{'46'} = 'F';
$Char{'47'} = 'G';
$Char{'48'} = 'H';
$Char{'49'} = 'I';
$Char{'4a'} = 'J';
$Char{'4A'} = 'J';
$Char{'4b'} = 'K';
$Char{'4B'} = 'K';
$Char{'4c'} = 'L';
$Char{'4C'} = 'L';
$Char{'4d'} = 'M';
$Char{'4D'} = 'M';
$Char{'4e'} = 'N';
$Char{'4E'} = 'N';
$Char{'4f'} = 'O';
$Char{'4F'} = 'O';
$Char{'50'} = 'P';
$Char{'51'} = 'Q';
$Char{'52'} = 'R';
$Char{'53'} = 'S';
$Char{'54'} = 'T';
$Char{'55'} = 'U';
$Char{'56'} = 'V';
$Char{'57'} = 'W';
$Char{'58'} = 'X';
$Char{'59'} = 'Y';
$Char{'5a'} = 'Z';
$Char{'5A'} = 'Z';
$Char{'5b'} = '{';
$Char{'5B'} = '{';
$Char{'5c'} = '\\';
$Char{'5C'} = '\\';
$Char{'5d'} = ']';
$Char{'5D'} = ']';
$Char{'5e'} = '^';
$Char{'5E'} = '^';
$Char{'5f'} = '_';
$Char{'5F'} = '_';
$Char{'60'} = '`';
$Char{'61'} = 'a';
$Char{'62'} = 'b';
$Char{'63'} = 'c';
$Char{'64'} = 'd';
$Char{'65'} = 'e';
$Char{'66'} = 'f';
$Char{'67'} = 'g';
$Char{'68'} = 'h';
$Char{'69'} = 'i';
$Char{'6a'} = 'j';
$Char{'6A'} = 'j';
$Char{'6b'} = 'k';
$Char{'6B'} = 'k';
$Char{'6c'} = 'l';
$Char{'6C'} = 'l';
$Char{'6d'} = 'm';
$Char{'6D'} = 'm';
$Char{'6e'} = 'n';
$Char{'6E'} = 'n';
$Char{'6f'} = 'o';
$Char{'6F'} = 'o';
$Char{'70'} = 'p';
$Char{'71'} = 'q';
$Char{'72'} = 'r';
$Char{'73'} = 's';
$Char{'74'} = 't';
$Char{'75'} = 'u';
$Char{'76'} = 'v';
$Char{'77'} = 'w';
$Char{'78'} = 'x';
$Char{'79'} = 'y';
$Char{'7a'} = 'z';
$Char{'7A'} = 'z';
$Char{'7b'} = '{';
$Char{'7B'} = '{';
$Char{'7c'} = '|';
$Char{'7C'} = '|';
$Char{'7d'} = '}';
$Char{'7D'} = '}';
$Char{'7e'} = '~';
$Char{'7E'} = '~';
$Char{'7f'} = ' ';
$Char{'7F'} = ' ';
$Char{'80'} = ' ';
$Char{'81'} = ' ';
$Char{'82'} = ' ';
$Char{'83'} = ' ';
$Char{'84'} = ' ';
$Char{'85'} = ' ';
$Char{'86'} = ' ';
$Char{'87'} = ' ';
$Char{'88'} = ' ';
$Char{'89'} = ' ';
$Char{'8a'} = ' ';
$Char{'8A'} = ' ';
$Char{'8b'} = ' ';
$Char{'8B'} = ' ';
$Char{'8c'} = ' ';
$Char{'8C'} = ' ';
$Char{'8d'} = ' ';
$Char{'8D'} = ' ';
$Char{'8e'} = ' ';
$Char{'8E'} = ' ';
$Char{'8f'} = ' ';
$Char{'8F'} = ' ';
$Char{'90'} = ' ';
$Char{'91'} = ' ';
$Char{'92'} = ' ';
$Char{'93'} = ' ';
$Char{'94'} = ' ';
$Char{'95'} = ' ';
$Char{'96'} = ' ';
$Char{'97'} = ' ';
$Char{'98'} = ' ';
$Char{'99'} = ' ';
$Char{'9a'} = ' ';
$Char{'9A'} = ' ';
$Char{'9b'} = ' ';
$Char{'9B'} = ' ';
$Char{'9c'} = ' ';
$Char{'9C'} = ' ';
$Char{'9d'} = ' ';
$Char{'9D'} = ' ';
$Char{'9e'} = ' ';
$Char{'9E'} = ' ';
$Char{'9f'} = ' ';
$Char{'9F'} = ' ';
$Char{'a0'} = ' ';
$Char{'A0'} = ' ';
$Char{'a1'} = ' ';
$Char{'A1'} = ' ';
$Char{'a2'} = ' ';
$Char{'A2'} = ' ';
$Char{'a3'} = ' ';
$Char{'A3'} = ' ';
$Char{'a4'} = ' ';
$Char{'A4'} = ' ';
$Char{'a5'} = ' ';
$Char{'A5'} = ' ';
$Char{'a6'} = ' ';
$Char{'A6'} = ' ';
$Char{'a7'} = ' ';
$Char{'A7'} = ' ';
$Char{'a8'} = ' ';
$Char{'A8'} = ' ';
$Char{'a9'} = ' ';
$Char{'A9'} = ' ';
$Char{'aa'} = ' ';
$Char{'AA'} = ' ';
$Char{'ab'} = ' ';
$Char{'AB'} = ' ';
$Char{'ac'} = ' ';
$Char{'AC'} = ' ';
$Char{'ad'} = ' ';
$Char{'AD'} = ' ';
$Char{'ae'} = ' ';
$Char{'AE'} = ' ';
$Char{'af'} = ' ';
$Char{'AF'} = ' ';
$Char{'b0'} = ' ';
$Char{'B0'} = ' ';
$Char{'b1'} = ' ';
$Char{'B1'} = ' ';
$Char{'b2'} = ' ';
$Char{'B2'} = ' ';
$Char{'b3'} = ' ';
$Char{'B3'} = ' ';
$Char{'b4'} = ' ';
$Char{'B4'} = ' ';
$Char{'b5'} = ' ';
$Char{'B5'} = ' ';
$Char{'b6'} = ' ';
$Char{'B6'} = ' ';
$Char{'b7'} = ' ';
$Char{'B7'} = ' ';
$Char{'b8'} = ' ';
$Char{'B8'} = ' ';
$Char{'b9'} = ' ';
$Char{'B9'} = ' ';
$Char{'ba'} = ' ';
$Char{'BA'} = ' ';
$Char{'bb'} = ' ';
$Char{'BB'} = ' ';
$Char{'bc'} = ' ';
$Char{'BC'} = ' ';
$Char{'bd'} = ' ';
$Char{'BD'} = ' ';
$Char{'be'} = ' ';
$Char{'BE'} = ' ';
$Char{'bf'} = ' ';
$Char{'BF'} = ' ';
$Char{'c0'} = ' ';
$Char{'C0'} = ' ';
$Char{'c1'} = ' ';
$Char{'C1'} = ' ';
$Char{'c2'} = ' ';
$Char{'C2'} = ' ';
$Char{'c3'} = ' ';
$Char{'C3'} = ' ';
$Char{'c4'} = ' ';
$Char{'C4'} = ' ';
$Char{'c5'} = ' ';
$Char{'C5'} = ' ';
$Char{'c6'} = ' ';
$Char{'C6'} = ' ';
$Char{'c7'} = ' ';
$Char{'C7'} = ' ';
$Char{'c8'} = ' ';
$Char{'C8'} = ' ';
$Char{'c9'} = ' ';
$Char{'C9'} = ' ';
$Char{'ca'} = ' ';
$Char{'CA'} = ' ';
$Char{'cb'} = ' ';
$Char{'CB'} = ' ';
$Char{'cc'} = ' ';
$Char{'CC'} = ' ';
$Char{'cd'} = ' ';
$Char{'CD'} = ' ';
$Char{'ce'} = ' ';
$Char{'CE'} = ' ';
$Char{'cf'} = ' ';
$Char{'CF'} = ' ';
$Char{'d0'} = ' ';
$Char{'D0'} = ' ';
$Char{'d1'} = ' ';
$Char{'D1'} = ' ';
$Char{'d2'} = ' ';
$Char{'D2'} = ' ';
$Char{'d3'} = ' ';
$Char{'D3'} = ' ';
$Char{'d4'} = ' ';
$Char{'D4'} = ' ';
$Char{'d5'} = ' ';
$Char{'D5'} = ' ';
$Char{'d6'} = ' ';
$Char{'D6'} = ' ';
$Char{'d7'} = ' ';
$Char{'D7'} = ' ';
$Char{'d8'} = ' ';
$Char{'D8'} = ' ';
$Char{'d9'} = ' ';
$Char{'D9'} = ' ';
$Char{'da'} = ' ';
$Char{'DA'} = ' ';
$Char{'db'} = ' ';
$Char{'DB'} = ' ';
$Char{'dc'} = ' ';
$Char{'DC'} = ' ';
$Char{'dd'} = ' ';
$Char{'DD'} = ' ';
$Char{'de'} = ' ';
$Char{'DE'} = ' ';
$Char{'df'} = ' ';
$Char{'DF'} = ' ';
$Char{'e0'} = ' ';
$Char{'E0'} = ' ';
$Char{'e1'} = ' ';
$Char{'E1'} = ' ';
$Char{'e2'} = ' ';
$Char{'E2'} = ' ';
$Char{'e3'} = ' ';
$Char{'E3'} = ' ';
$Char{'e4'} = ' ';
$Char{'E4'} = ' ';
$Char{'e5'} = ' ';
$Char{'E5'} = ' ';
$Char{'e6'} = ' ';
$Char{'E6'} = ' ';
$Char{'e7'} = ' ';
$Char{'E7'} = ' ';
$Char{'e8'} = ' ';
$Char{'E8'} = ' ';
$Char{'e9'} = ' ';
$Char{'E9'} = ' ';
$Char{'ea'} = ' ';
$Char{'EA'} = ' ';
$Char{'eb'} = ' ';
$Char{'EB'} = ' ';
$Char{'ec'} = ' ';
$Char{'EC'} = ' ';
$Char{'ed'} = ' ';
$Char{'ED'} = ' ';
$Char{'ee'} = ' ';
$Char{'EE'} = ' ';
$Char{'ef'} = ' ';
$Char{'EF'} = ' ';
$Char{'f0'} = ' ';
$Char{'F0'} = ' ';
$Char{'f1'} = ' ';
$Char{'F1'} = ' ';
$Char{'f2'} = ' ';
$Char{'F2'} = ' ';
$Char{'f3'} = ' ';
$Char{'F3'} = ' ';
$Char{'f4'} = ' ';
$Char{'F4'} = ' ';
$Char{'f5'} = ' ';
$Char{'F5'} = ' ';
$Char{'f6'} = ' ';
$Char{'F6'} = ' ';
$Char{'f7'} = ' ';
$Char{'F7'} = ' ';
$Char{'f8'} = ' ';
$Char{'F8'} = ' ';
$Char{'f9'} = ' ';
$Char{'F9'} = ' ';
$Char{'fa'} = ' ';
$Char{'FA'} = ' ';
$Char{'fb'} = ' ';
$Char{'FB'} = ' ';
$Char{'fc'} = ' ';
$Char{'FC'} = ' ';
$Char{'fd'} = ' ';
$Char{'FD'} = ' ';
$Char{'fe'} = ' ';
$Char{'FE'} = ' ';
$Char{'ff'} = ' ';
$Char{'FF'} = ' ';

$MAXSTR = 16;
1;
} # End the BEGIN

$Program = "DecodeIP";
$Version = "0.1";

Getopts('dhVXo:w:l:');

if (defined $opt_V || defined $opt_h) {
  print "$Program: $Version\n";
  print "  -V         - Version and this message\n";
  print "  -X         - Just hex from IP packets, no tcpdump header\n";
  print "  -d         - debug, default none\n";
  print "  -o offset  - offset into hex for start of IP header, default 0\n";
  print "  -w width   - output width of payload hex strings, default 8\n";
  print "  -l limit   - limit number of bytes ouput for payload, default 16\n";
  exit 0;
}

$DEBUG = (defined $opt_d) ? 1 : 0;
$HWS = (defined $opt_w) ? $opt_w : 8;
$OFFSET = (defined $opt_o) ? $opt_o * 2 : 0;
$LIMIT = (defined $opt_l) ? $opt_l  : 16;
$packetType = (defined $opt_X) ? $IP : 0;  # packets better be IP 

printf STDERR "Starting $0, HWS = $HWS, OFFSET = $opt_0\n" if ($DEBUG);
&main;
exit 0;

# Subroutine to convert hex string to text 
# Call: &xtoa ($str)
#
sub xtoa {

  my $Ascii = "";
  my ($str) = @_;
  $xtoa_l = length($str);
  for ($xtoa_i=0; $xtoa_i < $xtoa_l; $xtoa_i += 2) {
    $Ascii = $Ascii . $Char{substr($str,$xtoa_i,2)};
  }
  $Ascii;
}

# Subroutine to convert hex string to an intenger
# Call: &xtoi ($str)
#
sub xtoi {
  
  my $Number = 0;
  my ($str) = @_;

  $xtoi_l = length($str);
  for ($xtoi_i=0; $xtoi_i<$xtoi_l ; $xtoi_i++) {
    $ix = substr($str,$xtoi_i,1);
    $Number = ($Number * 16) + $HX{$ix};
  }
  $Number;
}

# Decode IPV4 protocol
# Call: &decodeIPV4 ($hex)
#
sub decodeIPV4 {
    local ($hex) = @_;

    $blobLength = (length $hex) / 2;
    printf STDERR "IP: %s\n", substr($hex,0,40) if ($DEBUG);
    return if ($blobLength < 20); # probably should say something about this.
    $_ = $hex;
    ($ver, $ihl, $tos, $len, $ident, $flags, $fragoffset,
    $ttl, $protocol, $hdrchksum, $sourceIP, $destIP,$rest) =
    m/^(.)(.)(..)(....)(....)(.)(...)(..)(..)(....)(........)(........)(.*)/;
    $ver = &xtoi($ver);
    $ihl = &xtoi($ihl);
    $tos = &xtoi($tos);
    $fu = $tos&3;
    $tos = $tos / 4;
    $dtr = $tos&7;
    $pre = $tos / 8;
    $len = &xtoi($len);
    $ident = &xtoi($ident);
    $flags = &xtoi ($flags);
    $fragoffset = &xtoi ($fragoffset);
    $fragoffset += 65536 if ($flags & 1);
    $flags = $flags / 2;
    $ctlflag = $FLAGS[$flags];
    $ttl = &xtoi($ttl);
    $protocol = &xtoi($protocol);
    $hdrchksum = &xtoi($hdrchksum);
    $_ = $sourceIP;
    (@saddr) = m/(..)(..)(..)(..)/;
    $_ = $destIP;
    (@daddr) = m/(..)(..)(..)(..)/;
    $Saddr = sprintf "%d.%d.%d.%d",
         &xtoi($saddr[0]), &xtoi($saddr[1]), &xtoi($saddr[2]), &xtoi($saddr[3]);
    $Daddr = sprintf "%d.%d.%d.%d",
         &xtoi($daddr[0]), &xtoi($daddr[1]), &xtoi($daddr[2]), &xtoi($daddr[3]);
  
    printf "\n";
    printf $IP0;
    printf $LBL1;
    printf $LBL2;
    printf $SEP0;
    printf $IP1, $ver,$ihl,$PRE[$pre],$DTR[$dtr],$FU[$fu],$len;
    printf $SEP0;
    printf $IP2, $ident, $ctlflag, $fragoffset;
    printf $SEP0;
    printf $IP3, $ttl, $protocol, $hdrchksum;
    printf $SEP0;
    printf $IP4, $Saddr;
    printf $SEP0;
    printf $IP5, $Daddr;
    $hdrBytes = $ihl * 4;
    $optionBytes = $hdrBytes - 20;
    &decodeOptions (substr ($hex, 40), $optionBytes, 0);
    if ($optionBytes < 0) {
        printf STDERR "$Saddr, IP IHL is less than 5, resetting.\n";
        $hdrBytes = 20;
    }
    $hex = substr ($hex, $hdrBytes * 2);
    printf STDERR "TRANS: %s\n", substr($hex,0) if ($DEBUG);
    if ($protocol == $TCP)
    {
        &decodeTCP ($hex);
    }
    elsif ($protocol == $UDP)
    {
        &decodeUDP ($hex);
    }
    elsif ($protocol == $ICMP)
    {
        &decodeICMP ($hex);
    }
    else {
        &decodeANY (substr ($hex, 0, $LIMIT*2));
    }
}

# Subroutine to dump hex for unsupported IP protocols
# Call: &decodeANY ($hex);
sub decodeANY {
    my ($hex) = @_;
    my $len = length($hex) / 2;

   # my $n = int((($len-1)/$MAXSTR) + 1) ;
    my $i = 0;
    while ($len>0)
    {
        my $m = $MAXSTR;
        if ($len < $MAXSTR) {$m = $len};
        my $str = substr($hex, $i, 2*$m);
        printf ("  :");
        for (my $k = 0; $k < $MAXSTR*2; $k = $k + $HWS)
        {
            $limit = $m*2;
            if ($k >= $limit)
            {
               printf ("  %${HWS}.${HWS}s");
            } else
            {
               printf ("  %-${HWS}.${HWS}s", substr($str,$k,$HWS));
            }
        }
        printf ("    : %-*s :\n",  $MAXSTR, xtoa($str));
        $i += 2*$MAXSTR;
        $len -= $MAXSTR;
    }
    if ($i) {
        print $SEP0;
    }
}

sub decodeOptions
{
    local ($hex, $optionBytes, $hdrtype) = @_;

    if ($optionBytes > 0)
    {
        printf "$SEP0";
        printf "$OPT0";
        printf "$SEP0";
        for ( $i = 0; $i < $optionBytes; $i++ )
        {
            if ( $i%4 == 0 ) {
	        if ($i == 0) {
                   print "  ";
                } else {
	           print "|\n";
                   printf "$SEP0";
		   printf "  ";
                }
            }
            $opt = substr($hex, $i*2, 2);
	    printf $OPT1, $opt;
        }
	print "|\n";
    }
    printf $SEP0;
}

sub decodeTCP {
    my ($hex) = @_;
    my $len = length($hex) / 2;
    my $x = 0;

    printf $TCP0;
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $TCP1, &xtoi( substr($hex, 0, 4) ), &xtoi( substr($hex, 4, 4) );  
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $TCPS, &xtoi( substr($hex, 8, 8) );
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $TCPA, &xtoi( substr($hex, 16, 8) );
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    $_ = substr($hex, 24, 8);
    ($offset, $flags, $window) = m/^(.)(...)(....)/;
    $offset = &xtoi($offset);
    $num = xtoi ($flags);
    $flags = sprintf "%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
                      ($num&0x800) ? 'X' : ' ',
                      ($num&0x400) ? 'X' : ' ', 
                      ($num&0x200) ? 'X' : ' ', 
                      ($num&0x100) ? 'X' : ' ',
                      ($num&0x80)  ? 'C' : ' ',
                      ($num&0x40)  ? 'E' : ' ',
                      ($num&0x20)  ? 'U' : ' ',
                      ($num&0x10)  ? 'A' : ' ',
                      ($num&0x8)   ? 'P' : ' ',
                      ($num&0x4)   ? 'R' : ' ',
                      ($num&0x2)   ? 'S' : ' ',
                      ($num&0x1)   ? 'F' : ' ';
    printf $TCPF, $offset, $flags, &xtoi($window) ;
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $TCPC, &xtoi( substr($hex, 32, 4) ), &xtoi( substr($hex, 36, 4) );
    $tcphdrBytes = $offset * 4;
    $optionBytes = $tcphdrBytes - 20;
    $x += $optionBytes;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    &decodeOptions (substr ($hex, 40), $optionBytes, $TCP);
    if ($optionBytes < 0) {
        printf STDERR "$Saddr, TCP Data Offset is less than 5, resetting.\n";
        $tcphdrBytes = 20;
    }
    $hex = substr ($hex, $tcphdrBytes * 2);
    if (length ($hex) > 0 ) {
        printf "$DATA";
        printf "$SEP0";
        &decodeANY (substr($hex, 0, $LIMIT*2));
    }
    return 1;
}

sub decodeUDP {
    my ($hex) = @_;
    my $len = length($hex) / 2;
    my $x = 0;

    printf $UDP0;
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $TCP1, &xtoi( substr($hex, 0, 4)), &xtoi( substr($hex, 4, 4));
    printf $SEP0;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    printf $UDP2, &xtoi( substr($hex, 8, 4)), &xtoi( substr($hex, 12, 4));
    printf $SEP0;
    $head = $len - 8;
    if ($head > 0) {
        printf "$DATA";
        printf "$SEP0";
        &decodeANY (substr($hex, 16, ($LIMIT > $head) ? $head*2 : $LIMIT*2));
    }
}

sub decodeICMP {
    my ($hex) = @_;
    my $len = length($hex)/2;
    my $x = 0;

    $_ = $hex;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    ($Type, $Code, $Checksum, $rest) = m/^(..)(..)(....)(.*)/;
    $Type = &xtoi($Type);
    $Code = &xtoi($Code);
    $Checksum = &xtoi($Checksum);
    printf $ICMP0;
    printf $SEP0;
    printf $ICMP1, $Type, $Code, $Checksum;
    $x += 4;
    if ($len < $x) {
       print $ERR0, $len;
       return 0;
    }
    $_ = $rest;
    # 3 of the 6 icmp formats have the same second 32 bits
    ($Id, $Sequence, $next) = m/^(....)(....)(.*)/;
    $Id = &xtoi($Id);
    $Sequence = &xtoi($Sequence);
# echo reply or echo
    if ($Type == 0 || $Type == 8)
    {
        printf $ICMPX, $icmpType[$Type], "$Code";
        printf $SEP0;
        printf $ICMPI, $Id, $Sequence;
        printf $SEP0;
        $datalen = $len - 8;
        &decodeANY (substr($hex, 16, (28 > $datalen) ? $datalen*2 : 56));
    } 
#Unreachable, Source Quench or Time Exceeded
    elsif ($Type == 3 || $Type == 4 || $Type == 11)
    {
        if ($Type == 3) {
        printf $ICMPX, $icmpType[$Type], $unreachCode[$Code];
        } elsif ($Type == 4) {
        printf $ICMPX, $icmpType[$Type], "$Code";
        } else {
        printf $icmpType[$Type], $exceedCode[$Code];
        }
        printf $SEP0;
        printf $ICMPU, substr($hex,8,8);
        printf $SEP0;
        printf $ICMPH;
        $datalen = $len - 8;
        &decodeANY (substr($hex, 16, (28 > $datalen) ? $datalen*2 : 56));
    }
#Parameter Problem
    elsif ($Type == 12 )
    {
        printf $icmpType[$Type], $parameterCode[$Code];
        printf $SEP0;
        printf $ICMPP, &xtoi(substr($hex,8,2)), substr($hex,10,6);
        printf $SEP0;
        printf $ICMPH;
        $datalen = $len - 8;
        &decodeANY (substr($hex, 16, (28 > $datalen) ? $datalen*2 : 56));
    }
# Redirect
    elsif ($Type == 5 )
    {
        printf $icmpType[$Type], $redirCode[$Code];
        printf $SEP0;
        $_ = substr($hex,8,8);
        (@gaddr) = m/(..)(..)(..)(..)/;
        $Gaddr = sprintf "%d.%d.%d.%d",
         &xtoi($gaddr[0]), &xtoi($gaddr[1]), &xtoi($gaddr[2]), &xtoi($gaddr[3]);
        printf $ICMPG, $Gaddr;
        printf $SEP0;
        $datalen = $len - 8;
        &decodeANY (substr($hex, 16, (28 > $datalen) ? $datalen*2 : 56));
    }
# Address Mask Request or Reply
    elsif ($Type == 17 || $Type == 18 || $Type == 15 || $Type == 16 )
    {
        printf $ICMPX, $icmpType[$Type], "$Code";
        printf $SEP0;
        printf $ICMPI, $Id, $Sequence;
        printf $SEP0;
        $_ = substr($hex,16,8);
        (@gaddr) = m/(..)(..)(..)(..)/;
        $Gaddr = sprintf "%d.%d.%d.%d",
         &xtoi($gaddr[0]), &xtoi($gaddr[1]), &xtoi($gaddr[2]), &xtoi($gaddr[3]);
        printf $ICMPA, $Gaddr;
    }
# Timestamp or Reply
    elsif ($Type == 13 || $Type == 14 )
    {
        printf $ICMPX, $icmpType[$Type], "$Code";
        printf $SEP0;
        printf $ICMPI, $Id, $Sequence;
        printf $SEP0;
        printf $ICMPO, substr($hex, 16, 8);
        printf $SEP0;
        $x += 4;
        if ($len < $x) {
            print $ERR0, $len;
            return 0;
        }
        printf $ICMPR, substr($hex, 24, 8);
        printf $SEP0;
        $x += 4;
        if ($len < $x) {
            print $ERR0, $len;
           return 0;
        }
        printf $ICMPT, substr($hex, 32, 8);
    } else {
	printf $ICMPUNK
        $datalen = $len - 8;
        &decodeANY (substr($hex, 16, (28 > $datalen) ? $datalen*2 : 56));
    }
    printf "\n";
    return;
} # End of decodeICMP

sub main {
  
    $hex = "";
    while (<>) {
        chomp;
        $nextline = $_;
        $len = length($nextline);
	$_ = $nextline;
        if (/^[\dabcdefABCDEF\s]+$/ && $packetType && $len > 0) {
            printf STDERR "INPUT: $_\n" if ($DEBUG);
            s/\s//g;
            $hex .= $_;
        } else {
            &decodeIPV4 (substr ($hex, $OFFSET)) if
                        ($hex && ($packetType == $IP));
    	    $hex = "";
            $_ = $nextline;
            $packetType = ( /frag|tcp|udp|icmp/ || $len == 0 || defined $opt_X) ? $IP : 0;
	
            printf "$nextline\n"
        }
    }
    &decodeIPV4 (substr ($hex, $OFFSET)) if
                ($hex && ($packetType == $IP));
    return;
}


More information about the Snort-users mailing list