At 2/23/03 11:04 PM +0100, Martin Regner wrote:
Martin Regner wrote:
<05 00 Number of packets stored (I think) = 5
< (only 5 will be visible since captured with demo version but there are really a few more packets in the file.
< The demo file that was included had value "06 00" and there was 6 packets that I could view)


Changing the value to 7 with a hex-editor made NetProb32 show the 7 first packets in the file.
Changing the value to 8 made NetProb32 show all 8 packets in the file.


<3C 00   number of octets  (size=64)
<3C 00   snaplen

Oooops, size=60 for these packets!

Good morning,


The attached Perl script will convert NetProb 1.34RL trace files into pcap formatted capture files. It is neither pretty nor well optimized, but it has worked on all of the files I have tried. I commented it heavily, so someone familiar with the wiretap import functions might be able to figure out how to add a NetProb option. If anyone has any other versions of NetProb, please convert those files and let me know how it goes. I am actually on the verge of replacing the 486/50MHz/MS-DOS machine that is running NetProb with a P200 running Knoppix and Ethereal. So I probably won't need this conversion for very long. However, it has been a big help reviewing the more than five dozen trace files I already have.

The only trick necessary for the conversion is in the date/time adjustment. In the DOS version of NetProb, you have to manually save the trace after terminating the capture. So the file is created after the fact. I worked out a way to adjust the time stamps based on the file create date/time minus the total elapsed time to the final packet. That assumes that the file was saved as soon as the capture was terminated, and was close enough for my needs. This version of NetProb will only keep the last 8000 packets, although the script should be able to handle more.

This script was written with TextPad, and run with ActiveState Perl 5.6, Build 622 on Windows NT4.

Bob McConnell
N2SPP
#! /usr/bin/perl

# Convert Netprobe trace file into tcpdump capture file.
# 
# Started 2/25/03 Bob McConnell
# Written with ActiveState Perl build 522 on Windows NT 4.0.
# 
# Reads a .trc file saved from DOS Netprob 1.34RL, converts the headers
# into pcap format and copies the packets. Since saving a capture file
# is a manual operation in Netprobe, done after terminating the caputure,
# the best way to estimate the actual start time is to subtract the last
# elapsed time from the file creation time. Assuming the save was done
# immediately after terminating the capture. Rather than read the whole
# file to get the last timestamp, look it up and enter it as an argument.
# stat() returns unix epoch->gmt, no zone conversion is done. Ethereal
# displays local time.
# Debug prints left in for now.
# 
# Netprob trace file format:
# 
# File header = 46 bytes.
# First four bytes 0x64, 0x00, 0x01, 0x00. May be usable as magic number.
# Next two bytes = Intel little endian word with number of packets in file.
# Next 40 bytes = 0x00.
#
# Packet header = 20 bytes.
# First two bytes = Intel lew with length of packet.
# Next two bytes =  "      "   "     "     " snapshot.
# Next four bytes = Intel double word with milliseconds elapsed since capture
# initiated.
# Remaining 12 bytes = 0x00.
# If snap length is less than packet length, the rest of the packet duplicates
# a previous packet. Reading short packets cannot truncate the previous
# data. DOS Netprobe will only save 8000 packets, wrapping around to delete
# the oldest when the limit is reached.
# 
# tcpdump capture file format:
# 
# File header = 24 bytes.
# First four bytes = magic number 0xD4, 0xC3, 0xB2, 0xA1.
# Next two bytes = Major version 0x02, 0x00.
# Next two bytes = Minor version 0x04, 0x00.
# Next eight bytes = 0x00.
# Next four bytes = 0x60, 0x00, 0x00, 0x00.
# Last four bytes = 0x01, 0x00, 0x00, 0x00.
# 
# Packet header = 16 bytes.
# First eight bytes = Unix timestamp, epoch seconds + microseconds.
# Next four bytes = packet snapshot lenght
# Last four bytes = original packet length.

use integer;

( $infile, $outfile, $timediff ) = @ARGV;

$infile = "" unless $infile;        # input file name
$outfile = "" unless $outfile;      # output file name
$timediff = -1 unless $timediff;    # elapsed seconds between capture start and file 
save

if (($infile eq "" ) || ( $outfile eq "" ) || ($timediff == -1)) {
    print "\nUsage: perl -w NP2pcap Infile Outfile Time\n";
    print "\n";
    exit 1;
}

open(INDAT, "< $infile.trc") || die "Can't open input file $infile.trc: $!\n";
$infile .= ".trc";
binmode (INDAT);

$write_secs = (stat(INDAT))[9];     # get file creation time
printf "file %s created at %s\n", $infile, scalar localtime($write_secs);
$write_secs -= $timediff;    # subtract seconds to estimate capture start time
printf "start time is %s\n", scalar localtime($write_secs);

sysread (INDAT, $indata, 4, 0);     # check file type. I only know of one.
if ((ord $indata != 0x64) || ( ord substr($indata, 1, 1) != 0x00) ||
   ( ord substr($indata, 2, 1) != 0x01) || ( ord substr($indata, 3, 1) != 0x00)) {
   print "Not a valid Netprob trace file.\n";
   exit 1;
   }

sysread (INDAT, $indata, 2, 0);      # number of packets in file
$tracelenth = ord $indata;
$tracelenth += (ord substr($indata, 1, 1)) * 256;

sysread (INDAT, $indata, 40, 0);   # read and discard rest of header

printf ("%s.trc, contains %d packets.\n", $infile, $tracelenth);

open(OUTDAT,">> $outfile.cap") || die "Can't create output file: $!\n";
binmode (OUTDAT);

# Write out a pcap style header. This duplicates the header from Windump 3.0beta.
$outdata = chr (0xd4) . chr (0xc3) . chr (0xb2) . chr (0xa1);   # pcap magic number
syswrite (OUTDAT, $outdata, 4, 0);
$outdata = chr (0x02) . chr (0x00) . chr (0x04) . chr (0x00);   # fake version numbers
syswrite (OUTDAT, $outdata, 4, 0);
$outdata = chr (0x00) . chr (0x00) . chr (0x00) . chr (0x00);
syswrite (OUTDAT, $outdata, 4, 0);
syswrite (OUTDAT, $outdata, 4, 0);
$outdata = chr (0x60) . chr (0x00) . chr (0x00) . chr (0x00);
syswrite (OUTDAT, $outdata, 4, 0);
$outdata = chr (0x01) . chr (0x00) . chr (0x00) . chr (0x00);   # link type Ethernet
syswrite (OUTDAT, $outdata, 4, 0);

$lastpkt = "";
$packetcount = 0;
$diflen = 0;

while( sysread (INDAT, $indata, 20, 0) ) {          # read packet header
    $plenth = (ord $indata);                            # Packet length
    $plenth += (ord (substr ($indata, 1, 1))) * 256;
    $slenth = (ord (substr ($indata, 2, 1)));           # Snapshot length
    $slenth += (ord (substr ($indata, 3, 1))) * 256;
    $timestamp = ord (substr ($indata, 4, 1));          # Elapsed time (ms)
    $timestamp += (ord (substr ($indata, 5, 1))) * 256;
    $timestamp += (ord (substr ($indata, 6, 1))) * 256 * 256;
    $timestamp += (ord (substr ($indata, 7, 1))) * 256 * 256 * 256;
    $msecs = $timestamp % 1000;     # convert time to milliseconds and seconds
    $timestamp /= 1000;

    $ctime = $write_secs + $timestamp;  # add init time
    $msecs *= 1000;                     # convert to microseconds

    sysread (INDAT, $inpkt, $slenth, 0);    # read packet data
    $packet = unpack ("h*", $inpkt);        # convert to hex string

    ++$packetcount;
    if ($plenth != $slenth) {
        ++$diflen;
        print " * ";                # copy tail of earlier packet
        $packet .= substr ($lastpkt, $slenth * 2, ($plenth - $slenth) * 2);
    }
    else {
        print "   ";
    }
    substr ($lastpkt, 0, $slenth * 2) = $packet;    # only write new data
    printf "Packet %d: slenth = %d, offset = %d.%03d:   ",
            $packetcount, $slenth, $timestamp, $msecs;

    printf "%x %x %x %x %x %x %x %x\n", ord (substr ($indata, 0, 1)), ord (substr 
($indata, 1, 1)),
            ord (substr ($indata, 2, 1)), ord (substr ($indata, 3, 1)),
            ord (substr ($indata, 4, 1)), ord (substr ($indata, 5, 1)),
            ord (substr ($indata, 6, 1)), ord (substr ($indata, 7, 1));

    $outdata = pack (VVVV, $ctime, $msecs, $plenth, $plenth);
    $outdata .= pack ("h*", $packet);

    syswrite (OUTDAT, $outdata, $plenth + 16, 0);
}

close INDAT;
close OUTDAT;
print STDERR "$diflen packets were compressed.\n";
if ($packetcount != $tracelenth) {
    printf STDERR "*** Incorrect packet count! (%d) ***\n", $packetcount;
}

1;

Reply via email to