perlpack

Understanding pack() and unpack() in Perl


I know there are libraries that can do this for me, but I want to learn pack() and unpack().

My goal is I have a user input an IP address and subnet mask, and then verify that it's valid.

One way I thought of doing it was "sprintf" and get a binary value of, let’s say, 192.168.1.1. That's an OK solution, but then I need to prepend the required amount of 0's to make it '8 bit'.

That seems like a lot of unnecessary work when pack can put things in a binary format. I used the N template I found in the documentation. My first goal was to get an IP address, convert it to binary, and convert it back.

$ip = "192.168.1.1";
$bi = pack("N*", $ip);
print unpack("N*", $bi), "\n";

And the output I got was 192, so obviously I don't understand what's going on here.

What exactly is going on here?


Solution

  • pack ("N*", $ip) takes an integer out of $ip and puts it into network byte order.

    What you want is packing the 4 decimal octets of the IP address as binary. No need to fiddle with endianness as the IP address string is already in big endian (The highest order byte is already at the start of the string).

    I also changed the * to a 4, IP addresses are always 4 octets long:

    $ip = "192.168.1.1";    
    $bi = pack "C4", split('\.', $ip);
    print join('.', unpack("C4",$bi)), "\n";