#!/usr/bin/perl
#
#  Argus-5.0 Client Software. Tools to read, analyze and manage Argus data.
#  Copyright (c) 2000-2024 QoSient, LLC
#  All rights reserved.
# 
#  THE ACCOMPANYING PROGRAM IS PROPRIETARY SOFTWARE OF QoSIENT, LLC,
#  AND CANNOT BE USED, DISTRIBUTED, COPIED OR MODIFIED WITHOUT
#  EXPRESS PERMISSION OF QoSIENT, LLC.
# 
#  QOSIENT, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
#  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS, IN NO EVENT SHALL QOSIENT, LLC BE LIABLE FOR ANY
#  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
#  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
#  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
#  THIS SOFTWARE.
#
#  radecode use tshark tools to decode user data 
#    
#  $Id: //depot/gargoyle/clients/examples/radecode/radecode.pl#3 $
#  $DateTime: 2014/10/07 15:00:33 $
#  $Change: 2938 $
#
# written by Carter Bullard and Dave Edelman
# QoSient, LLC
#

use strict;

use File::Temp qw/ :POSIX /;

#
#
# Since ~.rarc may modify the default settings, I use -X to reset everything to a known value before I use -n which cycles
# through the options based on the number of 'n's that it has seen and can lead to very strange results in some instances
# The other ra parameters that I use:
# -n do not translate port numbers to service names
# -u use UNIX time (seconds since the epoc)
# -p 6 use 6 digits of precision after the decimal point in the timestamp and anywhere else that it applies
# -M printer='hex' output the user data in the format that I need for this program
# -L -1 do not output any column headers
# -s proto sport dport stime saddr daddr smac dmac sttl stcpb suser:2000 output the following fields:
#    protocol as a protocol name (tcp, udp, icmp ...)
#    source port number
#    destination port number
#    start time for the flow record as a UNIX time and date stamp with six digits after the decimal point
#    source address
#    destination address
#    source MAC address
#    destination MAC address
#    source time to live
#    source base sequence number (only for TCP flows)
#    Source user data (a maximum of 2000 bytes which may inlcude full or partial data from one or more of the packets that make
#           up the flow all depending on the configuration of the capturing Argus (Argii) text2pcap and tshark deal with the
#           variations of user data with a pretty impressive amount of grace, the people attempting to read the output, not so much.
#
#
my $raoptions = " -X -n -u -p 3  -M printer='hex' -L -1 -s proto sport dport stime saddr daddr smac dmac sttl stcpb suser:2000";

my $lines = 0;
my $content = '';
my $cmd;

my $tmpFile = tmpnam();
my $ra = `which ra`;
my $tshark = `which tshark`;
my $text2pcap = `which text2pcap`;

# If requested to do so, text2pcap will generate mock headers for specified protocol stack layers that are not present in the hex dump
# there are no provisions for specifying much more than source and destination port which are then inserted into the created pcap
# Rather than modify the text2pcap source (easy enough to do but change coordination may be a problem) I modify the easy to identify
# fields in the decoded tshark output replacing the placeholder values with the actual values.
#
# as of this version, the replaced values are:
#       saddr
#       daddr
#       smac
#       dmac
#       sttl
#       stcbp
#
# Since text2pcap is able to deal with timestamp information, I use stime in the appropriate format
#
my $stime;
my $saddr;
my $daddr;
my $smac;
my $dmac;
my $sttl;
my $stcpb;
my $output;
my $ttlStr = "Time to live: ";

my $VERSION = "3.0.7.8";

chomp $ra;
chomp $tshark;
chomp $text2pcap;

my @args = ($ra, $raoptions, ' "'.join('" "',@ARGV).'"');
open(SESAME, "@args |");
while (<SESAME>) {
        chomp;
        if (/^\s*tcp\s+(\d+)\s+(\d+)\s+(\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.d+)\s+([0-9a-f\:]{17})\s+([0-9a-f\:]{17})\s+(\d+)\s+(\d+)/) {
                $cmd = "$text2pcap -T $1,$2 - $tmpFile \n ";
                $stime = $3;
                $saddr = $4;
                $daddr = $5;
                $smac = $6;
                $dmac = $7;
                $sttl = $8;
                $stcpb = $9;
                if ($lines > 0) {
                        $content .= "\n";
                        $lines = 0;
                }
                next;
        }
        if (/^\s*udp\s+(\d+)\s+(\d+)\s+(\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+([0-9a-f\:]{17})\s+([0-9a-f\:]{17})\s+(\d+)/) {
#       if (/^\s*udp\s+(\d+)\s+(\d+)/) {
                $cmd = "$text2pcap -u $1,$2 - $tmpFile \n ";
                $stime = $3;
                $saddr = $4;
                $daddr = $5;
                $smac = $6;
                $dmac = $7;
                $sttl = $8;
                if ($lines > 0) {
                        $content .= "\n";
                        $lines = 0;
                }
                next;
        }
        if (/^\s*0x([0-9a-f]{4,})\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+(..)(..)\s+/) {
                if ($lines == 0) {$content .= "$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 ";
                $lines++;
                }
                else {
                $content .= " $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 ";
                }
        }
}
$content .= "\n\n";
if ($lines > 0) {
        $ttlStr .= $sttl;
        system "echo \"$content\" \| $cmd";
        $cmd = "$tshark -V -r $tmpFile";
        $output = qx/$cmd/;
        unlink $tmpFile;
        $output =~ s/10.1.1.1/$saddr/g;
        $output =~ s/10.2.2.2/$daddr/g;
        $output =~ s/0a\:01\:01\:01\:01\:01/$smac/g;
        $output =~ s/0a\:02\:02\:02\:02\:02/$dmac/g;
        $output =~ s/Time to live\: 255/$ttlStr/g;
        print "$output";
}



