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

Hi perlmonks:

I have Mac running OS X/Yellow Dog Linux and PC running Linux.
If I run p0f http://lcamtuf.coredump.cx/p0f.shtml on Mac OS X or Yellow dog Linux on Power Mac G5 as:

p0f -Q /var/run/p0f.sock -0 'dst port 80' >>/dev/null &

and run ./p0fq.pl /var/run/p0f.sock src_host 0 dst_host 80

I get "P0f did not honor our query."

the p0fq.pl works fine If I run on x86 machine.

My question is whether this problem is caused by the use of pack function of script p0fq.pl because Mac is big endian and PC is little endian, could anyone recommend a working solution? the p0fq.pl script is as following:

use strict; use IO::Socket; use Net::IP; my $QUERY_MAGIC = 0x0defaced; my $QTYPE_FINGERPRINT = 1; die "usage: p0fq.pl p0f_socket src_ip src_port dst_ip dst_port" unless $#ARGV == 4; # Convert the IPs and pack the request message my $src = new Net::IP ($ARGV[1]) or die (Net::IP::Error()); my $dst = new Net::IP ($ARGV[3]) or die (Net::IP::Error()); print "$ARGV[1]\n"; my $query = pack("L L L N N S S", $QUERY_MAGIC, $QTYPE_FINGERPRINT, 0x +12345678, $src->intip(), $dst->intip(), $ARGV[2], $ARGV[4]); # Open the connection to p0f my $sock = new IO::Socket::UNIX (Peer => $ARGV[0], Type => SOCK_STREAM); die "Could not create socket: $!\n" unless $sock; # Ask p0f print $sock $query; my $response = <$sock>; close $sock; # Extract the response from p0f my ($magic, $id, $type, $genre, $detail, $dist, $link, $tos, $fw, $nat, $real, $score, $mflags, $uptime) = unpack ("L L C Z20 Z40 c Z30 Z30 C C C s S N", $response); die "Bad response magic.\n" if $magic != $QUERY_MAGIC; die "P0f did not honor our query.\n" if $type == 1; die "This connection is not (no longer?) in the cache.\n" if $type == +2; # Display result print "Genre : " . $genre . "\n"; print "Details : " . $detail . "\n"; print "Distance : " . $dist . " hops\n"; print "Link : " . $link . "\n"; print "Uptime : " . $uptime . " hrs\n";

Replies are listed 'Best First'.
Re: p0fq.pl and pack?
by ikegami (Patriarch) on Feb 19, 2007 at 21:53 UTC

    s, S and L use the system's endianness.
    x86's s corresponds to universal v, with sign correction.
    x86's S corresponds to universal v.
    x86's L corresponds to universal V.

    my $query = pack("L L L N N S S", ...);
    should be
    my $query = pack("V V V N N v v", ...);

    ... = unpack ("L L C Z20 Z40 c Z30 Z30 C C C s S N", $response);
    should be
    ... = unpack ("V V C Z20 Z40 c Z30 Z30 C C C v v N", $response);
    $score -= 65536 if $score > 32767;

    $score -= 65536 if $score > 32767;
    can also be written as
    $score = unpack('s', pack('S', $score));

      Thank you for the reply!

      I changed the pack and unpack to your suggestion, but I got "Bad response magic." error.

      perldoc -f pack:

      v An unsigned short in "VAX" (little-endian) order.
      V An unsigned long in "VAX" (little-endian) order. (These ’shorts’ and ’longs’ are _exactly_ 16 bits and _exactly_ 32 bits, respectively.)

      I don't understand what "$score -= 65536 if $score > 32767;" means, I don't have that in the original script, should I add it in?

        but I got "Bad response magic." error.

        What are the bytes of $response?

        I don't understand what "$score -= 65536 if $score > 32767;" means

        There is no code for "A signed short in 'VAX' (little-endian) order.", so I extracted an unsigned short, and that converts it to a signed short.