# Calea perl trafr - Mikrotik Script RouterOS

    Calea perl trafr
    System independent trafr script
    This small article describe the script wrote on perl which help you to get packets encapsulated by calea and captured by tcpdump or wireshark. You could upgrade it to catch traffic without tcpdump or wireshark.

    #!/usr/bin/perl -w
    #
    #  TZSP headers remover
    #
    #  You need this modules:
    #  Data-HexDump		0.02
    #  Net-Pcap		0.16
    #  Net-Pcap-Reassemble	0.04
    #  NetPacket		0.41.1
    #
    # usage: trafr -r filename.pcap [ -s observed_ip ] [ -d ] [ -c count ]

    use strict;
    use Net::Pcap qw ( :datalink :functions );
    use NetPacket::Ethernet;
    use NetPacket::IP;
    use NetPacket::UDP;
    use Data::HexDump;
    use Getopt::Std;

    our($opt_d, $opt_r, $opt_c, $opt_s);
    my ($err,$dumpOUT,$errdumpOUT,$count,$pcap,$dumper,$errdumper);

    getopt('rcs');
    getopts('d');

    my $dumpIN = $opt_r or die "No input file!Use -r";	# input pcap file
    my $debug = $opt_d; # do you need debug?
    print "test: ".$debug."" if ($debug);
    if (!$opt_c) { $count = -1}
    else { $count = $opt_c}	# how many packets to process? (for debug)
    my $counter = 1;
    my $observedIP = $opt_s; # ip that you looking for
    #my $errdumpOUT = 'errpackets.pcap';# file for errors packets (for debug)
    $dumper = undef; # output file
    my $destport=37008;	# Port used for TZSP streaming (default 37008)

    # --- Output file name
    if ($dumpIN !~ m/^(\S+)\.pcap$/i){ $dumpOUT = $dumpIN.'.ok.pcap'}
    else { $dumpOUT = $1.'.ok.pcap'}

    # --- Errors packets file name
    if ($debug){
    if ($dumpIN !~ m/^(\S+)\.pcap$/i){ $errdumpOUT = $dumpIN.'.err.pcap'}
    else { $errdumpOUT = $1.'.err.pcap'}
    }

    # --- Open input file
    $pcap = Net::Pcap::pcap_open_offline($dumpIN, \$err)
    or die $err;

    # --- Open file for errors packets
    # --- (for debug)
    $errdumper = Net::Pcap::pcap_dump_open($pcap,$errdumpOUT) if ($debug);

    # --- Process
    Net::Pcap::pcap_loop($pcap, $count, \&headoff_tzsp, "user data");

    # --- Close all open files
    Net::Pcap::close($pcap);
    Net::Pcap::pcap_dump_close($dumper) if ($dumper);
    Net::Pcap::pcap_dump_close($errdumper) if ($debug);

    # --- Delete error file if it empty
    if ($debug) {
    if ( -e $errdumpOUT and -s $errdumpOUT == 24){
    system("rm $errdumpOUT") == 0
    or die "rm -f ".$errdumpOUT." failed: $?";
    }
    }

    # --- TZSP head remove function
    sub headoff_tzsp {

    print STDOUT "=============================================================================" if ($debug);
    my($user_data, $header, $packet) = @_;

    # --- Decapsulate packet
    my $ether = NetPacket::Ethernet->decode($packet);
    if ( $ether->{type} ne NetPacket::Ethernet->ETH_TYPE_IP) {
    print STDOUT "Not an IP packet. Type = $ether->{type} instead of " . NetPacket::Ethernet->ETH_TYPE_IP if ($debug);
    $counter++;
    return;
    }
    my $ip = NetPacket::IP->decode($ether->{data});
    if ( $ip->{proto} ne NetPacket::IP->IP_PROTO_UDP ) {
    print STDOUT "Not an UDP packet. Proto = $ip->{proto} instead of " . NetPacket::IP->IP_PROTO_UDP if ($debug);
    $counter++;
    return;
    }
    my $udp = NetPacket::UDP->decode($ip->{data});
    if ( $udp->{dest_port} ne 37008 ) {
    print STDOUT "Wrong Dest port. Dest_port=$udp->{dest_port} instead of 37008" if ($debug);
    $counter++;
    return;
    }

    # --- For debug
    #    print STDOUT $counter," ",
    #        $ip->{'src_ip'}, ":", $udp->{'src_port'}, " -> ",
    #        $ip->{'dest_ip'}, ":", $udp->{'dest_port'},
    #	" length: ", $udp->{'len'}, " chksum: ",$udp->{'cksum'},
    #	" fragment: ",$ip->{'foffset'},"" if ($debug);
    #    print STDOUT HexDump $udp->{data} if($debug);

    # --- Cut TZSP bytes
    my $tzspheader = substr $udp->{data}, 0, 5;
    my $tzspdata = substr $udp->{data}, 5;
    #    print STDOUT HexDump $tzspheader if($debug);

    # --- Check is the header is TZSP
    if (unpack ('H*',$tzspheader) eq '010000120a'){
    if (!$dumper) {
    # --- Open output file as IEEE802.11
    my $linktype = Net::Pcap::datalink_name_to_val('IEEE802_11');
    my $dummy=Net::Pcap::open_dead($linktype,2500);
    $dumper = Net::Pcap::pcap_dump_open($dummy, $dumpOUT);
    }
    } elsif (unpack ('H*',$tzspheader) eq '0100000101'){
    if (!$dumper) {
    # --- Open output file as Ethernet
    my $linktype = Net::Pcap::datalink_name_to_val('EN10MB');
    my $dummy=Net::Pcap::open_dead($linktype,2500);
    $dumper = Net::Pcap::pcap_dump_open($dummy, $dumpOUT);
    }
    } else {
    print STDERR $counter," Maybe wrong tzsp header? -> ",unpack ('H*',$tzspheader),"" if ($debug);
    Net::Pcap::pcap_dump($errdumper, $header, $packet) if ($debug);
    $counter++;
    return;
    }
    #    print STDOUT HexDump $tzspdata if($debug);

    # --- Process included packet
    my $ethertzsp = NetPacket::Ethernet->decode($tzspdata);
    my $iptzsp = NetPacket::IP->decode($ethertzsp->{data});

    # --- If it's the right ip
    if (!$observedIP || ( $iptzsp->{'src_ip'} eq $observedIP or $iptzsp->{'dest_ip'} eq $observedIP)){
    #	Net::Pcap::pcap_dump($dumper, $header, $packet) if ($debug);
    # --- If yes, add it to output file
    Net::Pcap::pcap_dump($dumper, $header, $tzspdata);
    }
    else {
    print STDERR $counter," Maybe wrong include packet? ",$iptzsp->{'src_ip'}," -> ",$iptzsp->{'dest_ip'},"";
    }
    $counter++;
    }
    Credit: https://wiki.mikrotik.com/wiki/Calea_perl_trafr