Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I parse space separated STDIN hex strings unpacked in Perl?

I have a Java program that spits out, in space-separated hexadecimal format, 16 bytes of raw packet received over the network. Since I dont want to change that code, I am piping the result to a Perl script that, theoretically, can simply unpack this from STDIN into recognizable variables. The following is a sample of the line input to my Perl file:

FF FF 09 7D 10  01  07  01 00  02 00  1D 00  00 00  00 00  06 00  07 00 
|--garbage-----|c--|c--|int---|int---|int---|int---|int---|int---|int---|

(c is for char/byte, int for 16bit integer variable)

I initially wanted to use unpack to cleanly separate each input line into variables that I needed. However, because of the space delimit in the string, I am not sure how to handle it (I can use 'A' as a template, but then I might as well just use split!)

Is there a elegant way of using unpack()? I am not a Perl master, but the other way is to, as I suggested before, use split and then manually convert each hex to a byte, and then use bit manipulations and masks to get what I want. Any other suggestions (if unpack doesnt save the day)?

like image 915
intiha Avatar asked Feb 01 '10 22:02

intiha


2 Answers

Assuming those ints are in big-endian order, use

#! /usr/bin/perl

use warnings;
use strict;

# for demo only
*ARGV = *DATA;

while (<>) {
  my @fields = unpack "x5C2n7",
               pack "C*",
               map hex, split;

  print "[", join("][" => @fields), "]\n";
}

__DATA__
FF FF 09 7D 10 01 07 01 00 02 00 1D 00 00 00 00 00 06 00 07 00

It starts off by packing in the bytes (C*) according to their values. The unpack template has the following parts:

  • x5 skips five bytes
  • C2 decodes two unsigned char values
  • n7 decodes seven 16-bit big-endian unsigned integers

Output:

$ ./dump-packets
[1][7][256][512][7424][0][0][1536][1792]
like image 109
Greg Bacon Avatar answered Sep 19 '22 13:09

Greg Bacon


If you want to use unpack on unpacked data, you'll need to pack it again first. And you'll need to remove the spaces before you do that.

In other words,

$line =~ tr/ //d;          # remove spaces
$line = pack 'H*', $line;  # convert hex to binary
# Now you can use unpack.
like image 37
Porculus Avatar answered Sep 18 '22 13:09

Porculus