Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Pack/Unpack with B32 and related query

by Anonymous Monk
on Jul 28, 2004 at 02:04 UTC ( [id://377905]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
I'd like some help from anyone who can explain how the following pack/unpack examples work (in simple terms please :-) ).
All the examples I've looked at on the web mention the B32 format only briefly, use binary representation instead of decimal (as used by this prog) and only have 1 value after the 'B32, instead of 2 values as below.
The code below is based on a program I need to amend. I'd also like to know why the 2 different ways of retrieving the mask both work/produce the same answer.
Thanks for any help
Cheers
Chris
#!/usr/bin/perl -w + use IO::Socket; use strict; + my ( $key, %new, $str1, $str2, $str3, $mask, $ip, $ip_disp, $mask_disp ); + $str1 = '202.6.145.136'; $str2 = '29'; $str3 = '29'; print "$str1, $str2, $str3\n"; $mask = pack ('B32', (1 x $str2), (1 x (32 - $str2))); $new {AA} {inet_aton ($str1) & $mask} = $mask . pack ('B32', (1 x $str3), (1 x (32 - $str3 +))); + for $ip ( keys %{$new{AA}} ) { $ip_disp = join('.',unpack('CCCC',$ip)); print "unpack ip CCCC = $ip_disp\n\n"; + $mask_disp = join('.',unpack('CCCC',$new{AA}{$ip})); print "unpack mask CCCC = $mask_disp\n\n"; + $mask_disp = join('.',unpack('CCCC',substr($new{AA}->{$ip},0,4))); print "substr/unpack CCCC mask = $mask_disp\n"; } exit;

Replies are listed 'Best First'.
Re: Pack/Unpack with B32 and related query
by pg (Canon) on Jul 28, 2004 at 04:00 UTC

    I came up this example, which could give a very intuitive answer:

    use strict; use warnings; my $a = "abcdabcd"; { my $b = join('.',unpack('CCCC',$a)); print $b, "\n"; } { my $b = join('.',unpack('CCCC',substr($a,0,4))); print $b, "\n"; } { my $b = join('.',unpack('(CCCC)*',$a)); print $b, "\n"; } { my $b = join('.',unpack('(CCCC)*',substr($a,0,4))); print $b, "\n"; }

    The output is:

    97.98.99.100 97.98.99.100 97.98.99.100.97.98.99.100 97.98.99.100

    Here is the explanation:

    1. The pattern in the first block says: take the first 4 bytes, and interprete each of them as unsigned char. The bold part is an implicit substr.
    2. The second block uses the same pattern, but it substr $a first. Base on the explanation of the first block, now we know that what the program does is "take the first 4 bytes of the first 4 bytes", which has no difference from 'take the first 4 bytes'. So this produces the same thing as case 1.
    3. Now we switch to a new pattern '(CCCC)*', which says repeatedly group every 4 consecutive bytes together. Without substr, as $a is 8 bytes long, it matches the pattern twice, or more precisely once but produces two groups. So it uses all 8 bytes.
    4. Same pattern as case 3, but substr'd down to 4 bytes first, now you only have enough bytes to match the pattern once and produce one group.
Re: Pack/Unpack with B32 and related query (fix)
by tye (Sage) on Jul 28, 2004 at 05:15 UTC

    Replace

    (1 x $str2), (1 x (32 - $str2))

    with

    (1 x $str2) . (0 x (32 - $str2))

    B32 want a string of 32 characters (preferably where each character is "0" or "1"). When you give it a string of fewer than 32 chars, then it assumes "0"s for the missing chars. Your second string is simply being ignored.

    - tye        

Re: Pack/Unpack with B32 and related query
by esskar (Deacon) on Jul 28, 2004 at 02:26 UTC
    well, the 'CCCC' is the reason... C (An unsigned char value) unpacks a byte to a number. and CCCC unpacks 4 bytes to 4 numbers... so it is no different to unpack only the first 4 chars in the string or the entire string
Re: Pack/Unpack with B32 and related query
by Anonymous Monk on Jul 28, 2004 at 04:13 UTC
    pg,
    thx for that. It's very helpful, I hadn't realised the implicit substr.
    Actually, as far as the mask stuff goes, what I actually wanted to know is why a value that is Hash-of-Hash seems to be the same as Hash-of-HashRef value?
    Explanations of the pack(B32... ) codes sections still invited.
Re: Pack/Unpack with B32 and related query
by Anonymous Monk on Jul 28, 2004 at 06:59 UTC
    Thx tye,
    when I was researching it I did wonder why I couldn't find a similar example to the code I have to deal with, but as I implied above, this area is all new to me... and the originator is long gone...sigh.
    Your version makes much more sense.
    If you or anyone can explain why anyone would want to store an IP address and mask in such a complex way, I'd appreciate it.
    ie why (ip & mask) => 2 concat copies of the mask?
    (yes, its not an accident that $str2=$str3...)

    Similarly, there are 3 other examples I need to understand that look like this style:
    $mask = pack ('B32', (1 x $2), (1 x (32 - $2))); $new {ISPP} {inet_aton ($1) & $mask} = + $mask . pack ('B32', (1 x 32));
    ie the 2nd copy of mask is being set to 32 x 1 ?
    (I intend to change the assignment of $mask to use your concat rule).
    Cheers
    Chris

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://377905]
Approved by graff
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-25 08:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found