Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the simplest way of adding one to a binary string in Perl?

Tags:

math

binary

perl

I have a variable that contains a 4 byte, network-order IPv4 address (this was created using pack and the integer representation). I have another variable, also a 4 byte network-order, subnet. I'm trying to add them together and add one to get the first IP in the subnet.

To get the ASCII representation, I can do inet_ntoa($ip&$netmask) to get the base address, but it's an error to do inet_ntoa((($ip&$netmask)+1); I get a message like:

 Argument "\n\r&\0" isn't numeric in addition (+) at test.pm line 95.

So what's happening, the best as I can tell, is it's looking at the 4 bytes, and seeing that the 4 bytes don't represent a numeric string, and then refusing to add 1.

Another way of putting it: What I want it to do is add 1 to the least significant byte, which I know is the 4th byte? That is, I want to take the string \n\r&\0 and end up with the string \n\r&\1. What's the simplest way of doing that?

Is there a way to do this without having to unpack and re-pack the variable?

like image 675
Daniel Papasian Avatar asked Oct 21 '08 14:10

Daniel Papasian


2 Answers

What's happening is that you make a byte string with $ip&$netmask, and then try to treat it as a number. This is not going to work, as such. What you have to feed to inet_ntoa is.

pack("N", unpack("N", $ip&$netmask) + 1)

I don't think there is a simpler way to do it.

like image 126
Leon Timmermans Avatar answered Sep 20 '22 00:09

Leon Timmermans


Confusing integers and strings. Perhaps the following code will help:

use Socket;

$ip = pack("C4", 192,168,250,66); # why not inet_aton("192.168.250.66")
$netmask = pack("C4", 255,255,255,0);

$ipi = unpack("N", $ip);
$netmaski = unpack("N", $netmask);

$ip1 = pack("N", ($ipi&$netmaski)+1);
print inet_ntoa($ip1), "\n";

Which outputs:

192.168.250.1
like image 45
Liudvikas Bukys Avatar answered Sep 18 '22 00:09

Liudvikas Bukys