Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

I am pretty new on the block. I have a log file from WireShark that I am trying the process and extract some information, namely src, dst and data.

see below a snipet of the log file:

Frame 76 (113 bytes on wire, 113 bytes captured) Ethernet II, Src: Intel_83:fb:e0 (00:0c:f1:83:fb:e0), Dst: HewlettP_c6 +:9e:c9 (00:14:c2:c6:9e:c9) Internet Protocol, Src: 201.20.2.1 (201.20.2.1), Dst: 201.20.2.2 (201. +20.2.2) Transmission Control Protocol, Src Port: apc-3052 (3052), Dst Port: ts +dos390 (1237), Seq: 1, Ack: 462008081, Len: 59 Source port: apc-3052 (3052) Destination port: tsdos390 (1237) Sequence number: 1 (relative sequence number) [Next sequence number: 60 (relative sequence number)] Acknowledgement number: 462008081 (relative ack number) Header length: 20 bytes Flags: 0x18 (PSH, ACK) Window size: 65535 Checksum: 0x9681 [incorrect, should be 0x8704 (maybe caused by "TC +P checksum offload"?)] Data (59 bytes) 0000 00 00 00 37 00 00 2f 0d 00 00 c0 06 00 00 00 27 ...7../....... +.' 0010 43 3a 5c 4d 4b 53 5c 75 74 72 61 5f 52 65 6c 65 C:\MKS\utra_Re +le 0020 61 73 65 34 2e 30 5c 55 74 72 61 5c 75 68 74 5c ase4.0\Utra\uh +t\ 0030 75 65 75 68 74 2e 63 00 00 00 b0 ueuht.c.... Data: 0000003700002F0D0000C00600000027433A5C4D4B535C75...
For each src and dst, the data below has to be packed and send over a TCP/IP connection. Can any monk show me how to pack all the data into one string? I have already establiched the socket related frame work.

Thanks

Replies are listed 'Best First'.
Re: Extracting data from a WireShark log
by GrandFather (Saint) on Apr 28, 2008 at 21:37 UTC

    With three key components: regular expressions, hex and pack, you can generate a fairly clean solution. Consider:

    use strict; use warnings; while (<DATA>) { next unless /^(?:[0-9a-z]{4})\s+(?:([0-9a-z]{2}\s)){16}/i; my @chars = map hex, /(?<=\s)([0-9a-z]{2})\s/gi; my $str = pack ('C16', @chars); print $str; } __DATA__ Checksum: 0x9681 [incorrect, should be 0x8704 (maybe caused by "TC +P checksum offload"?)] Data (59 bytes) 0010 43 3a 5c 4d 4b 53 5c 75 74 72 61 5f 52 65 6c 65 C:\MKS\utra_Re +le 0020 61 73 65 34 2e 30 5c 55 74 72 61 5c 75 68 74 5c ase4.0\Utra\uh +t\ 0030 75 65 75 68 74 2e 63 00 00 00 b0 ueuht.c....

    Prints:

    C:\MKS\utra_Release4.0\Utra\uht\

    I skipped the data line containing nulls and other interesting characters, not because the code won't handle them (it will), but because they may not print so well. Oh, and the map is there to apply hex to each of the substrings returned from the regex.


    Perl is environmentally friendly - it saves trees
Re: Extracting data from a WireShark log
by pc88mxer (Vicar) on Apr 28, 2008 at 21:28 UTC
    This is a common parsing pattern:
    ...open LOGFILE... my (@list, %info); while (<LOGFILE>) { if (/^Frame /) { # detect start of new data record if (%info) { push(@list, { %info }) } # save last collected record %info = (); # start with blank record } elsif (/^ *Source port: (\S+)\s+(\S+)/) { $info{source_port} = $1; # also save $2? } elsif (/^ *Destination port: (\S+)\s+(\S+)/) { $info{dest_port} = $1; } elsif (/^[\da-f]{4}\s+[\da-f\s]+/i) { push(@{$info{data}}, $_); # save data lines } } if (%info) { # must check at end of loop push(@list, { %info }); } # @list contains parsed Frame records
    And here's one way to convert the saved data lines to bytes:
    my $bytes; for my $line (@{$info->{data}}) { if ($line =~ m/^[\da-f]{4}\s*(([\da-f]{2} )+)/i) { my $hex = $1; $hex =~ s/\s//g; $bytes .= pack("H*", $hex); } }

      What if we could declare a new copy of my %frame each time we detect the start of a new frame record?

      We wouldn't need to initialize %info = (). We wouldn't need to test if (%info). We could store \%frame instead of the clever but busy { %info }.

      All it takes is loop labels:

      # detect start of new data record my $FRAME_BEGINNING = qr/^Frame /; # store parsed Frame records my @frame_list; SKIP: while (<DATA>) { next SKIP if !/$FRAME_BEGINNING/; FRAME: while (!eof) { my %frame; DETAIL: while (<DATA>) { last DETAIL if /$FRAME_BEGINNING/; if (/^ *Source port: (\S+)\s+(\S+)/) { $frame{source_port} = $1; # also save $2? } if (/^ *Destination port: (\S+)\s+(\S+)/) { $frame{dest_port} = $1; } if (/^[\da-f]{4}\s+[\da-f\s]+/i) { push @{$frame{data}}, $_; # save data lines } } push @frame_list, \%frame; } }
Re: Extracting data from a WireShark log
by wade (Pilgrim) on Apr 28, 2008 at 21:43 UTC