Q:

Creating IP hierarchical list in PHP

I have a database table storing IP adresses, wich look like this:
 E_ID IP MASK

I want to make it to look like this:
E_ID Parent_ID IP MASK

So that I can easily get my IP adresses tree:
  80.17.0.0/18 (id=1 parent id = -1)
        80.17.0.0/24 (id=2, parent id=1)
            80.17.0.0/27 (id=3, parent id=2)
                80.17.0.0/31  (id=4, parent id=3)
                80.17.0.2/31  (id=5, parent id=3)
                80.17.0.4/31  (id=6, parent id=3)
                80.17.0.6/31  (id=7, parent id=3)
                80.17.0.8/31  (id=8, parent id=3)
                80.17.0.12/31  (id=9, parent id=3)
            80.17.0.32/27  (id=10, parent id=2)
                80.17.0.32/30 (id=11, parent id=10) 
                    80.17.0.32/32 (id=12, parent id=11) 
                    80.17.0.33/32 (id=13, parent id=11) 
                    80.17.0.34/32 (id=14, parent id=11) 
                    80.17.0.35/32 (id=15, parent id=11)     

All IPs and Masks are BINGINT (ip2long()).
What I have came up with:
$sql = "SELECT IP, Mask, E_ID
        FROM test
        ORDER BY `IP`, `Mask` ASC";

$result = mysqli_query($db, $sql) or die(mysqli_error($db));

$space = array();
$i = 0;
array_push($space, mysqli_fetch_assoc($result));

while($r = mysqli_fetch_assoc($result)){
    if(!ipvsnet(long2ip($r['IP']), long2ip($space[$i]['IP']), long2ip($space[$i]['Mask']))){
        array_push($space, $r);
        $i++;
    }

function ipvsnet($ip, $network, $mask){
    if(((ip2long($ip))&(ip2long($mask))) == ip2long($network)){
        return 1;
        } else {
        return 0;
    }
}

This gives me only main parent adresses. I don't understant how to find deeper nodes, because I don't know how deep each brach is. Thank you in advance.

A:

By the looks of things you are trying to sort/organize your IP addresses by network id, then subnet mask, then node id. I think you misunderstood the role of a subnet mask in IP addressing (which is a very common mistake man, I made this mistake too once upon a time :)   ). 
A subnet mask is used to separate a network id from an IP address. A subnet mask is a binary number that consists of an uninterrupted series of 1 bits which begins from the most significant bit of a binary word(4 byte binary value). For example:
11110000.00000000.00000000.00000000 // subnet_mask: /4
11111000.00000000.00000000.00000000 // subnet_mask: /5
11011000.00000000.00000000.00000000 // not a legal bitmask because of the 0 bit

When you consider a random IP address such as 74.125.224.197 (gonna do a little math here) we get the bit pattern:
01001010.01111101.11100000.11000101 // This is the same as 74.125.224.197

Now if we have a subnet mask for this particular IP of say:
11110000.00000000.00000000.00000000

Then the network id is going to be the logical AND of the subnet mask and the IP address:
    01001010.01111101.11100000.11000101 // ip
  & 11110000.00000000.00000000.00000000 // subnet mask
---------------------------------------
    01000000.00000000.00000000.00000000 // Network Id

Along logically similar lines, the node id is going to be the logical AND of the IP address and the /negation/ of the subnet mask:
/* negation of subnet mask via XOR */
    11110000.00000000.00000000.00000000 // subnet mask
XOR 11111111.11111111.11111111.11111111 
---------------------------------------
    00001111.11111111.11111111.11111111 // negation of subnet mask

/* getting the node id from the IP address using the negation of subnet mask */
    00001111.11111111.11111111.11111111 // negation of subnet mask
&   01001010.01111101.11100000.11000101 // original IP address
---------------------------------------
    00001010.01111101.11100000.11000101 // the node Id

The point of all this is to set up a contradiction to your understanding of the nature of the subnet mask and therefore your sort order. Consider a subnet mask like this:
    01001010.01111101.11100000.11000101 // original IP address of google
&   11000000.00000000.00000000.00000000 // different subnet mask
---------------------------------------
    01000000.00000000.00000000.00000000 // same network id(sort of) as above

How do we differentiate between what we generated this time versus the previous time we calculated the network id. The answer has to do with the subnet mask. The subnet mask is really about determining the network id. The IP address and the subnet mask should be considered together since you require both to determine a network id(which is what it looks like you are trying to order by).
If you want to organize your data for meaningful manipulation, consider first translating the raw IP address + subnet mask into proper network id and node id parts. The rest will quickly fall into place for you. 
I truly hope this helps man!

