add the issubnet and isconflicting code checks for ipv6
authorpaulr <me@pjr.cc>
Mon, 13 Sep 2010 06:25:09 +0000 (16:25 +1000)
committerpaulr <me@pjr.cc>
Mon, 13 Sep 2010 06:25:09 +0000 (16:25 +1000)
lib/ip.php
lib/www.php
unittest/iptogmp.php [new file with mode: 0644]

index 585643c..3a31d0b 100644 (file)
@@ -4,7 +4,7 @@ function ipversion($ip)
 {
        $ipv4 = ereg('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', $ip);
        $ipv6 = ereg("^[0-9a-fA-F:]+$", $ip);
-       
+
        error_log("ipversion, $ip, $ipv4, $ipv6");
        if($ipv4 == 1) return 4;
        if($ipv6 == 1) return 6;
@@ -16,21 +16,25 @@ function ipversion($ip)
 function ip6ToLongStr($ip)
 {
        if(ipversion($ip)!=6) return false;
-       
+
        $pss = explode(":", $ip);
        $ns = count($pss);
-       
+
        $nstr = "";
        foreach($pss as $ele) {
+               echo "ele: $ele\n";
                if($nstr != "") {
                        $nstr .= ":";
+                       echo "add colon\n";
                }
-               if(strlen($ele < 1)) {
+               if(strlen($ele)<1) {
                        // this is where we pad 8-count of 0000:
+                       echo "add pad count\n";
                        $pds = 8-$ns+1;
                        for($i=0; $i < $pds; $i++) {
-                               $nstr .= "0000";
+                               $nstr .= "0000:";
                        }
+                       $nstr = rtrim($nstr, ":");
                } else if(strlen($ele) < 4) {
                        $nstr .= str_pad($ele, 4, "0", STR_PAD_LEFT);
                } else {
@@ -43,26 +47,51 @@ function ip6ToLongStr($ip)
 // this function converts an ip address to a comparable integer
 // so we can bounds-check.
 // it returns an array of [firstnum][lastnum]
-function ip6ToComp($ip, $mask)
+// this is without a doubt one of the ugliest things i've ever done.
+function ip6ToGmp($ip, $mask)
 {
-       if($ipversion($ip)!=6) return false;
+       if(ipversion($ip)!=6) return false;
+
+       $ipone = ip::truncateNetwork($ip, $mask);
+       $iponeap = $ipone."::0";
+       $rip = ip6ToLongStr($iponeap);
        
-       $rip = ip6ToLongStr($ip);
+       $riphex = "0x".str_replace(":", "", $rip);
        
+       // f**king ugly
+       $sns = 8-($mask / 16);
+               
+       $slt = $ipone;
+       for($i = 0; $i < $sns; $i++) {
+               $slt .= ":FFFF";
+       }
+
+       $endhex = "0x".str_replace(":", "", ip6ToLongStr($slt));
+       
+       echo "$rip, $ipone, $iponeap, $riphex, $slt, $endhex\n";
+       
+       // now we gmp_init
+       $gmpone = gmp_init($riphex);
+       $gmptwo = gmp_init($endhex);
+       
+       $array["start"] = $gmpone;
+       $array["end"] = $gmptwo;
+       
+       return $array;
 }
 
 function ip4ToComp($ip, $mask)
 {
-       
+
 }
 
 class ip {
-       
+
        static function isValid($ip, $mask = 0)
        {
-               
+
                $ver = ipversion($ip);
-               
+
                if($ver == 0) return 0;
 
                if($ver == 6) {
@@ -72,11 +101,11 @@ class ip {
                                        return false;
                                } else {
                                        $sns = $mask / 16;
-                                       
+                                               
                                        // now check that we have $sns number of subnets specified
                                        $pss = explode(":", $ip);
                                        $ns = count($pss);
-                                       
+                                               
                                        // we need to specify an error we can throw back at the user
                                        if($ns < $sns) {
                                                error_log("no 2, $ns, $sns, $ip");
@@ -89,27 +118,27 @@ class ip {
                                                        return false;
                                                }
                                        }
-                                       
+                                               
                                        // we are still a valid ipv6 ip address/mask
                                        error_log("Valid");
                                        return true;
                                }
                        }
                }
-               
+
                if($ver == 4) {
                        if($mask != 0) {
                                return $ip;
                        }
                }
        }
-       
+
        static function truncateNetwork($ip, $mask)
        {
                $ver = ipversion($ip);
-               
+
                if($ver == 0) return false;
-               
+
                if($ver == 6) {
                        if($mask != 0) {
                                if($mask%16 != 0) {
@@ -117,18 +146,18 @@ class ip {
                                        return false;
                                } else {
                                        $sns = $mask / 16;
-                                       
+                                               
                                        // now check that we have $sns number of subnets specified
                                        $pss = explode(":", $ip);
                                        $ns = count($pss);
-                                       
+                                               
                                        // we need to specify an error we can throw back at the user
                                        if($ns < $sns) {
                                                error_log("no 2, $ns, $sns, $ip");
                                                print_r($pss);
                                                return false;
                                        }
-                                       
+                                               
                                        $slt = "";
                                        for($i = 0; $i < $sns; $i++) {
                                                if($i!=0) $slt .= ":";
@@ -138,25 +167,25 @@ class ip {
                                                }
                                                $slt .= "".$pss[$i];
                                        }
-                                       
+                                               
                                        // we are still a valid ipv6 ip address/mask
                                        error_log("Valid");
                                        return $slt;
                                }
                        }
                }
-               
+
                if($ver == 4) {
                        if($mask != 0) {
                                return $ip;
                        }
                }
        }
-       
+
        function addSupernet($name, $sn, $mask, $desc)
        {
                global $db;
-               
+
                if(ip::isValid($sn, $mask)) {
                        $sn = ip::truncateNetwork($sn, $mask);
                        $sql = "insert into supernet values (NULL, '$name', '$sn', '$mask', '$desc')";
@@ -165,33 +194,90 @@ class ip {
                }
                return false;
        }
-       
+
        function addSubnet($name, $subnet, $mask, $desc, $super)
        {
                global $db;
                if(ip::isValid($subnet, $mask)) {
-                       $sn = ip::truncateNetwork($sn, $mask);
+                       $subnet = ip::truncateNetwork($subnet, $mask);
                        // ("sn_id" INTEGER PRIMARY KEY AUTOINCREMENT,"snid_id" INTEGER,"sn_ip" TEXT,"sn_mask" TEXT,"sn_name" TEXT, "sn_desc" TEXT);';
-                       //if(!isSubnet($subnet, $mask, $super)) return "Is not a valid subnet"; 
-                       
+                       if(!$this->isSubnet($subnet, $mask, $super)) return "Is not a valid subnet of the super range";
+                       if(!$this->isConflicting($subnet, $mask, $super)) return "Is conflicting with an existing allocation";
+                               
                        $sql = "insert into subnet values (NULL, '$super', '$subnet', '$mask', '$name', '$desc')";
                        error_log("sql: $sql");
                        $db->dbobject->query($sql);
                        return true;
                }
        }
-       
+
        function isSubnet($subnet, $mask, $superid)
        {
-               return true;
+               global $db, $wwwConnector;
+
+               $res = $db->dbobject->query("select * from supernet where sn_id=='$superid'");
+               
+               foreach($res as $row) {
+                       $sn = $row["sn_ip"];
+                       $sm = $row["sn_mask"];
+               }
+               
+               if(ipversion($sn) == 6) {
+                       // we ip6 to gmp the main subnet...
+                       $aone = ip6ToGmp($sn, $sm);
+                       
+                       // we ip6togmp the sub sub...
+                       $atwo = ip6ToGmp($subnet, $mask);
+                       
+                       // then we gmp compare the two... subnet[start] must be higher then (or equal) $supernet[start] and subnet[end] must be lower then or equal too $supernt[end];
+                       $cmp1 = gmp_cmp($aone["start"], $atwo["start"]);
+                       $cmp2 = gmp_cmp($aone["end"], $atwo["end"]);
+                       
+                       error_log("cmp1, $cmp1, cmp2, $cmp2");
+                       // in order to be a subnet, $cmp1 should be 0 or negative, $cmp2 should be 0 or positive
+                       if($cmp1 <= 0&&$cmp2 >= 0) return true;
+                       return false;
+               }
+               if(ipversion($sn) == 4) {
+                       // ERR, TODO
+               }
+               return true;            
        }
-       
+
        // this function returns true if it is NOT conflicting
        function isConflicting($subnet, $mask, $superid)
        {
+               global $db, $wwwConnector;
+
+               if(ipversion($subnet) == 6) {
+                       $res = $db->dbobject->query("select * from subnet where snid_id=='$superid'");
+                               
+                       // we ip6togmp the sub sub...
+                       $atwo = ip6ToGmp($subnet, $mask);
+
+                       foreach($res as $row) {
+                               $sn = $row["sn_ip"];
+                               $sm = $row["sn_mask"];
+                               
+                               // we ip6 to gmp the main subnet...
+                               $aone = ip6ToGmp($sn, $sm);
+                               
+                               // in order to be not a collision, must be either $aone["end"] is lower then atwo["start"] or aone["start"] is higher then atwo["end"] 
+                               $cmp1 = gmp_cmp($aone["end"], $atwo["start"]);
+                               $cmp2 = gmp_cmp($aone["start"], $atwo["end"]);
+                               
+                               error_log("conflighting cmp1, $cmp1, cmp2, $cmp2 ".gmp_strval($aone["end"])." - ".gmp_strval($aone["start"])." - ".gmp_strval($atwo["end"])." - ".gmp_strval($atwo["start"])." - ");
+                               
+                               if($cmp1 < 0) return true;
+                               if($cmp2 > 0) return true;
+                               
+                               return false;
+                               
+                       }
+               }
                return true;
        }
-       
+
        public $supers = "";
        public $subs = "";
 }
index f38f5e8..3e23621 100644 (file)
@@ -267,10 +267,11 @@ function www_ip_allocateSubRange()
        $desc = $_REQUEST["subdesc"];
        
        $myip = new ip();
-       if($myip->addSubnet($name, $subip, $mask, $desc, $superid)) {
+       $err = $myip->addSubnet($name, $subip, $mask, $desc, $superid);
+       if($err ===true) {
                header("Location: index.php?notice=range added");
        } else {
-               header("Location: index.php?error=invalid ipaddress");
+               header("Location: index.php?error=$err");
        }
 }
 
diff --git a/unittest/iptogmp.php b/unittest/iptogmp.php
new file mode 100644 (file)
index 0000000..adf7a9f
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+require_once("../lib/lib.php");
+
+$ipa = "2003:3:2:2:3:3::1";
+$ipasn = "96";
+
+ip6ToGmp($ipa, $ipasn);
+
+$ipa = "2003:3:2:2:3::1";
+$ipasn = "64";
+
+ip6ToGmp($ipa, $ipasn);
+
+//$ipa = "2003:";
+//$ipasn = "16";
+
+//ip6ToGmp($ipa, $ipasn);
+
+
+?>
\ No newline at end of file