The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. September 19, 2019, 06:00:39 AM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Converting IP Adrresses to integers and back  (Read 8201 times)
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« on: April 23, 2007, 11:26:53 AM »

This is a PHP adaptation of NutBalls ASP code for storing IP addresses as big ints. I have made this about as efficient as I know how... if anyone else has ideas that'd be great. Note that if you use the defined constants then you'll need to "include" this code rather than put it inline - that's because the defines will happen _after_ your code alls the functions and you'll get nasty Div by Zero errors. Also, in the IntToIP conversion I just couldn't figure out why PHP was returning the 2s compliment of the value rather than the real deal... probably something to do with the mod operator. Anyway, this works correctly. I also learned something during this exercise - the ^ is not the exponent operator in PHP D'oh!  ROFLMAO

Code:
define('_OCT0', pow(256, 3));
define('_OCT1', pow(256, 2));
define('_OCT2', 256);
function IPtoInt($inStr)
{
if (!preg_match('/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/', $inStr, $parts))
throw new Exception("IPtoInt: Invalid IP Address ($inStr)");

return ($parts[1] * _OCT0) + ($parts[2] * _OCT1) + ($parts[3] * _OCT2) + $parts[4];
}

function InttoIP($inInt)
{
$oct4 = $inInt % 256;
$oct4 = ($oct4 < 0) ? 256 + $oct4 : $oct4;
return
(($inInt / _OCT0) % 256) . '.' .
(($inInt / _OCT1) % 256) . '.' .
(($inInt / _OCT2) % 256) . '.' .
$oct4;
}
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
cdc
Expert
****
Offline Offline

Posts: 105


View Profile
« Reply #1 on: April 23, 2007, 12:06:14 PM »

Quote
I also learned something during this exercise - the ^ is not the exponent operator in PHP D'oh!  ROFLMAO

I would have guessed **, but it looks like they implemented it with a function.

<edit>was missing a / </edit>
« Last Edit: April 23, 2007, 12:23:23 PM by perkiset » Logged

Will code for food.
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #2 on: May 07, 2007, 04:13:20 PM »

Here it is done in PERL by Dirk:

http://www.perkiset.org/forum/perl/converting_ip_addresses_to_integers_and_vice_versa-t174.0.html;new

Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
Fatty
Rookie
**
Offline Offline

Posts: 11


View Profile
« Reply #3 on: May 09, 2007, 10:42:50 AM »

Since you're multiplying by powers of 2 why not use shifts?

IP_int = octet1 << 24 + octet2 << 16 + octect3 << 8 + octet4

If you're storing in a DB as an int you've got INET_ATON and INET_NTOA... Let the DB worry about it.

Fatty
Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #4 on: May 09, 2007, 10:51:47 AM »

IP_int = octet1 << 24 + octet2 << 16 + octect3 << 8 + octet4
You're completely right Fatty - that'd be easier on the math processing I believe.

If you're storing in a DB as an int you've got INET_ATON and INET_NTOA... Let the DB worry about it.
Dirk covered that in a discussion about this very topic - these threads are more about just leaving code out there for someone with a specific need ie., "I need to do it in PHP." - but thanks

/p
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
spazdr8cr
n00b
*
Offline Offline

Posts: 4


View Profile
« Reply #5 on: May 06, 2008, 10:46:37 PM »

Hi everybody, and thanks for a great resource, epsecially Perkiset.

I love the notice that the topic is old, as I am frequently guilty of reviving old threads. However I must do so again  Grin

Trying to use this code I may have found an error, or I may be making an error myself. I convert the IP to an integer, and then when I try to convert the integer back to an IP, the last octet is always 255. Is this an error in the code or am I screwing it up somehow? Probably the latter. I am using the code given above by Perkiset, only modified to supply an IP and output results to the browser:

Code:
<?php

define
('_OCT0'pow(2563));
define('_OCT1'pow(2562));
define('_OCT2'256);

function 
IPtoInt($inStr)
{
if (!preg_match('/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/'$inStr$parts)) 
throw new Exception("IPtoInt: Invalid IP Address ($inStr)");

return ($parts[1] * _OCT0) + ($parts[2] * _OCT1) + ($parts[3] * _OCT2) + $parts[4];

}

function 
InttoIP($inInt)
{
$oct4 $inInt 256;
$oct4 = ($oct4 0) ? 256 $oct4 $oct4;
return 
(($inInt _OCT0) % 256) . '.' 
(($inInt _OCT1) % 256) . '.' .
(($inInt _OCT2) % 256) . '.' .
$oct4;
}

$ip1 "206.248.172.160";

echo 
IPtoInt($ip1)."<br><br>";

//run script to get result of IPtoInt, then insert below

$ip2 "3472403616";

echo 
InttoIP($ip2);

?>

So I am using the code as given by Perkiset, except for the echoes I added myself. I run the script once to get the integer from the first function, then insert it into the code, and then run it again to see if i get the original IP back. But the last octet is always 255. Am I doing something wrong or is the code wrong?

I calculated the result of IptoInt manually using a calculator, it seems correct.

The InttoIp I'm not sure of, I'm not familiar with that code at all, particularly "$oct4 = ($oct4 < 0) ? 256 + $oct4 : $oct4;" ... I have no idea what that means. So I'm at a loss there. Not familiar with the "?" or the ":" in this context.

Thanks!
Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #6 on: May 06, 2008, 11:24:48 PM »

Hey Spaz -

Well, I was baffled because it works fine on my machines... but all of my production servers (where I tested it) are big ol' tweaked out 64 bit machines... I just ran it on a smaller machine and got the same answer, 255. This is clearly a PHP overflow problem, but I'm not sure how ATM... I'll do a little poking around and see what I can see.

/p
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
nutballs
Administrator
Lifer
*****
Offline Offline

Posts: 5627


Back in my day we had 9 planets


View Profile
« Reply #7 on: May 07, 2008, 06:19:16 AM »

if there is a MODULUS in there somewhere, i would look at that. In ASP (at least on 32 bit systems) you would overflow on mod. I assume thats what the % is.

my IP code is somewhere in here from that original post, though its asp, the concept is the same for the whacky math.

the basics are, divide the number by 2 first. then do all the math, then remember if it was an odd or even number.
Logged

I could eat a bowl of Alphabet Soup and shit a better argument than that.
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #8 on: May 07, 2008, 07:32:18 AM »

It is the mod operator NBs, (%) - overflows on older and smaller, works fine on bigger and newer. 

PHP docs say that in the event of an overflow, PHP reinterprets an INT as a FLOAT so that you have enough digit width ... but that does not seem to be happening. Before I concede to the math I'd like to see if I can tell PHP to do it right first...
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
spazdr8cr
n00b
*
Offline Offline

Posts: 4


View Profile
« Reply #9 on: May 07, 2008, 09:47:28 AM »

Thanks for the replies guys.

This was running on my shared hosting (php 5.2). I tried running it in OSX this morning on my somewhat old (non-Intel) G5 (php 4.4) and got the same result.

Incidentally I discovered something that was interesting and a good lesson for me. Although when I wrote this tester script I felt kind of lame just typing in the result of the first function as in:

Code:
$ip2 = "3472403616";

it turns out had i done

Code:
$ip2 = IPtoInt($ip1);

it seemingly works fine, and I wouldn't have noticed the problem until much later when I tried to pull these out of the database and convert them.
Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #10 on: May 07, 2008, 10:48:02 AM »

Actually it is my Mac that I tried it on as well and got the error, but this is an Intel 8 core 64b machine... so I'da thunk that there'd not be the problems. I'm wondering if it is a compile switch or something now...
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
spazdr8cr
n00b
*
Offline Offline

Posts: 4


View Profile
« Reply #11 on: May 07, 2008, 11:58:19 AM »

I spent the last while translating nutballs' code from here: http://www.perkiset.org/forum/asp_net/classicasp_ip_to_num_and_num_to_ip_for_database_storage-t72.0.html;msg263#msg263 into php. it seems to work although i only tried it on a couple of ip's so far. Good learning experience, never looked at ASP before. Anyway this seems to work

Code:
define('_OCT0', pow(256, 3));
define('_OCT1', pow(256, 2));
define('_OCT2', 256);

function InttoIP($inInt)
{
$oct4 = $inInt % 256;
$oct4 = ($oct4 < 0) ? 256 + $oct4 : $oct4;
$a = (($inInt / _OCT0) % 256);
$b = (($inInt / _OCT1) % 256);
$c = (($inInt / _OCT2) % 256);

// this is the nutballs stuff, or at least my version of it

$tempnum = intval($inInt/2);
$tempnum = ($tempnum*2);
$adjust = $inInt - $tempnum;
$d = ((intval(($inInt/2)) % 128)*2)+$adjust;

//

$newip = $a . "." . $b . "." . $c . "." . $d;
return $newip;

}

Thanks guys.
Logged

No links in signatures please
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #12 on: May 07, 2008, 12:17:11 PM »

Try this Spaz - I compressed the maths to one line and spit out the return value without any string concatenations, which is way faster.

Code:
<?php
function InttoIP($inInt)
{
$oct4 $inInt 256;
$oct4 = ($oct4 0) ? 256 $oct4 $oct4;

$a = (($inInt _OCT0) % 256); 
$b = (($inInt _OCT1) % 256);
$c = (($inInt _OCT2) % 256);
$d = ((intval(($inInt/2)) % 128) * 2) + ($inInt - (intval($inInt/2)) * 2);

return "$a.$b.$c.$d";
}
?>

Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
spazdr8cr
n00b
*
Offline Offline

Posts: 4


View Profile
« Reply #13 on: May 07, 2008, 01:20:57 PM »

You rock Perk, thanks!  Praise
Logged

No links in signatures please
Pages: [1]
  Print  
 
Jump to:  

Perkiset's Place Home   Best of The Cache   phpMyIDE: MySQL Stored Procedures, Functions & Triggers
Politics @ Perkiset's   Pinkhat's Perspective   
cache
mart
coder
programmers
ajax
php
javascript
Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks


Valid XHTML 1.0! Valid CSS!