Jump to content

PHP: Get network address from IP?

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
4 replies to this topic

#1
FireGator

FireGator

    Learning Programmer

  • Members
  • PipPipPip
  • 37 posts
Hello,

A bit of background, for my administration panel I am attempting to get a network address from an IP to store as a range, to store large IP blocks as a single block for caching or analysis.

A few examples of what I am talking about:
192.168.6.255/8 -> 192.0.0.0
192.168.6.255/16 -> 192.168.0.0
64.128.128.254/24 -> 64.128.128.0

I began by convert the IP address into a numeric such as so:
$octets = explode('.', $addr);
$range = ($octets[0] << 24 + $octets[1] << 16 + $octets[2] << 8 + $octets[3]);

That got me fairly far, but I lack the knowledge compliment the range and get an IP back.
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]
>++++++++[<++++>-] <.>+++++++++++

#2
dbug

dbug

    Programmer

  • Members
  • PipPipPipPip
  • 155 posts
I think this is what you need:

$addr = (($range >> 24) & 0xFF) . '.' . (($range >> 16) & 0xFF) . '.' . (($range >> 8) & 0xFF) . '.' . ($range & 0xFF);


#3
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,124 posts
@dbug: best use bitmasks.

@FireGator:
It can be a trivial task to utilize PHP's ip2long/long2ip functions to store the IP as an unsigned int and apply the bitmask instead of your shifting (it relies on internals functions, less memory used).
Bitmasks 0xffffff00 for CIDR /24, 0xffff0000 for /16, 0xff000000 for /8 although you can compress it into a single routine:

function netmask($ip, $cidr) {
    $bitmask = $cidr == 0 ? 0 : 0xffffffff << (32 - $cidr);
    return long2ip(ip2long($ip) & $bitmask);
}

print netmask('192.168.6.255', 16);
You can learn more about CIDR conventions here to better understand what I wrote: Classless Inter-Domain Routing - Wikipedia, the free encyclopedia
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#4
FireGator

FireGator

    Learning Programmer

  • Members
  • PipPipPip
  • 37 posts
Nullw0rm, you just saved me days and money to get that part done efficiently. I read up a bit on CIDR but still fail to comprehend what the /16 /24 /32 are specifically for, I notice you apply the bit masks through bitwise and to truncate the integer with the range which is awesome, but what specifically do those refer to?

Thanks, FireGator.
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]
>++++++++[<++++>-] <.>+++++++++++

#5
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,124 posts

FireGator said:

I read up a bit on CIDR but still fail to comprehend what the /16 /24 /32 are specifically for[...]

As you're aware of the gritty details of the bases I'll break out my box drawing skills (heh) to better explain it:
[FONT=Courier New]     ┌────────────────────────────────────┐
Octet│    127  .   168  .    1   .   128  │
     ├────────────────────────────────────┤
BITS │ 11110011 10101000 00000001 10000000│
     ├────────────────────────────────────┤
CIDR │     8       16       24       32   │ 
     └────────────────────────────────────┘[/FONT]
As you can see it is as simple as your deconstruction of each octet in your original code, 4.3.2.1/16 would be 4.3.0.0, because only the first 16 bits are kept, the rest discarded (You were right about the truncation).
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.