develooper Front page | perl.beginners | Postings from February 2011

Re: Help on a socket problem FIX

Thread Previous | Thread Next
Ted Mittelstaedt
February 24, 2011 23:33
Re: Help on a socket problem FIX
Message ID:
On 2/24/2011 2:05 AM, John W. Krahn wrote:
> Ted Mittelstaedt wrote:
>> OK since nobody helped me (sniff, sniff) I had to figure it out myself.
>> Here is the problem code in the fragment:
>> $sockaddr = 'S n a4 x8';
>> replacing it with
>> $sockaddr = 'x C n a4 x8';
>> fixed the problem. The template for the pack command was wrong.
>> Th first two bytes are length (0) and family, both of which are unsigned
>> char, so 'x C' (or 'n') handles those.
> Why is 'x8' at the end of that string?

8 null bytes of padding

Do you know what is does

A description of what it does is available here:

it basically pads out the binary data that is being fed to
the connect() function to the correct length for the 16 byte
binary structure connect() uses.

The Perl connect() function requires SOCKET, NAME.  In the code
the author used "S" as the socket.  The connect function (per
the docs) "requires NAME to be a packed address of the appropriate type 
for the socket."

The original pack template of S n a4 x8 was  "An unsigned short value of 
16 bits" (2 bytes) "unsigned short in network big endian value" (2 
bytes) "string of arbitrary binary value 4 long" (4 bytes) "8 null 
bytes" (8 bytes)  This gives us our 16 bytes dictated in <netinet/in.h>

IMHO the author probably used 'S n a4 x8' because that pack template
appears in most if not all of the various tutorials and texts
scattered around the Internet. (and which all contain a lot of hand
waving when it comes to the nitty-gritty)  Remember my warning about 
using black boxes you don't want to understand!

The corrected pack template of x C n a4 x8 was "Null byte" (1 byte) 
"unsigned char value" (1 byte) "unsigned short in network big endian 
value" (2 bytes) "string of arbitrary binary value 4 long" (4 bytes) "8 
null bytes" (8 bytes)   This also gives us our 16 bytes with one
critical difference - the pack command now knows that the data that
it's expected to stuff into byte 2 is an unsigned char value.

These were used in:

$that = pack ($sockaddr, $AF_INET, $port, $thataddr);

So, after applying the template the main change is that we
are stuffing AF_INET into byte 2 is an unsigned char value.

In other words, it's x is 0, AF_INET is C, port 119 is n,
and the IP address is a4, and the last 8 bytes is zeros. (x8)

At least, this is MY understanding of it.  If it is wrong, say

The $64,000 question in all of this is WHY DID THE 'S n a4 x8'
WORK in the older FreeBSD 6.4 version, the current Ubuntu version,
and in a lot of other code people have used.  It appears to be
basically wrong.  I'd love to know why it "worked".  And incidentally
the original person who pointed this out years ago on another
mailing list (that led me to this solution) didn't have an
answer for that, either.

FreeBSD has a reputation for being very nasty to wrong-written
code.  Linux has a reputation for accepting all sorts of
wrong-written code and "trying to do the right thing"  I would
assume that the newer Perl version became more strict somehow,
and the newer FreeBSD version glommed on to that in it's
Perl build, while the Perl install on Ubuntu made it less strict in 
accordance with Linux'es more laid-back philosophy about working with
sloppy code.  There is probably a Perl compile flag that can be
set if I recompiled Perl on FreeBSD 8 that would break it again
so the original wrong code would "work"

  and why
> it is there?
> Have you read and of W. Richard Stevens' books?

No, I did the "Internetworking with TCP/IP" series by Comer, not the
TCP/IP Illustrated" series by Stevens.  That was a while ago when
we still used real paper books. ;-)


> John

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About