IPv4 Adressen, Netzwerke und eine Library für PHP

Zum Rechnen mit IPv4 gibt es in PHP ein paar Dinge zu beachten

Zu beachten ist, daß PHP intern 32-Bit-Integer vorzeichenbehaftet betrachtet. Untenstehende kleine Library wird diesem Sachverhalt gerecht und hat sich in verschiedenen Anwendungen bewährt. Download hier!

<?php

# Rechnen mit IPv4-Adressen
class IPv4{
    public $DATA = array();
    public $BITCMP = array();
    function __construct($ip, $ma){
        $this->DATA['IP'] = $ip;
        
        # Die Maske ist als Maskenlänge 0..30 angegeben
        preg_match("/^\d+$/", $ma, $matches );
        if( $matches ){
            $masklen = $matches[0];
            if( $masklen > 32 ){ throw new Exception("Maskenlänge ungültig!"); }
            if( $masklen == 31 ){ throw new Exception("Maskenlänge ungültig!"); }
            
            $masknum = $this->masklenton($masklen);
            $this->DATA['MASKLEN'] = $masklen;
        }
        else{
            $class = __CLASS__;
            $t = new $class($ma,0); # Maske als IP-Addr 
            $t->bitcmp( new $class('255.255.255.255',0) );
            $tlen = min( $t->BITCMP );
            # Mit $tlen zurückrechnen auf Dezimalschreibweise der Maske
            if( $ma != $t->inetntoa($t->masklenton($tlen)) ){
                throw new Exception("Netzmaske ungültig!");
            }

            $masklen = $tlen;            
            $masknum = $this->masklenton($masklen);
            $this->DATA['MASKLEN'] = $masklen;
        }

        # Die übergebene IP-Adresse auf Gültigkeit prüfen    
        $ipnum = $this->inetaton($ip);
        $decim = $this->inetntoa($ipnum);
        if( $decim != $ip ){
            throw new Exception("IPv4-Adresse '$ip' ungültig!");
        }
    
        # Netzadresse und Broadcastadresse
        $this->DATA['NETADDR'] = $this->inetntoa($ipnum & $masknum);
        $this->DATA['BCADDR']  = $this->inetntoa($ipnum |~ $masknum);
        
        # Numerische longint fixierten
        $this->ipnum = $ipnum;
        $this->masknum = $masknum;
        
        # PHP rechnet intern mit Vorzeichen
        # von daher werden der Lesbarkeit wegen
        # die Numerischen Werten vorzeichenlos abgelegt
        $this->DATA['MASKNUM'] = sprintf("%u",$masknum);
        $this->DATA['IPNUM']   = sprintf("%u", $ipnum);
        $this->DATA['NETMASK'] = $this->inetntoa( $masknum );

        # Anzahl möglicher Hosts berechnen
        $this->DATA['HOSTS'] = $this->DATA['MASKLEN'] == 32 ? 'Single Host' : 
            sprintf("%u", $this->inetaton($this->DATA['BCADDR']) - $this->inetaton($this->DATA['NETADDR']) - 1 );
        
        # Erster und letzter Host im Subnetz
        $this->DATA['FIRST'] = $this->addx($this->DATA['NETADDR'], 1);
        $this->DATA['LAST'] = $this->addx($this->DATA['BCADDR'], -1);
    }

    function data(){
        return $this->DATA;
    }

    function addx($addr, $x){
        $num = $this->inetaton($addr) + $x;
        return $this->inetntoa($num);
    }


    # Dezimal zu Numerisch
    function inetaton($ipa){
        $octs = explode(".", $ipa);
        if( count($octs) != 4 ){ 
            throw new Exception("Syntax für Adresse '$ipa' ungültig!"); 
        }
        $bin = pack("CCCC", $octs[0], $octs[1], $octs[2], $octs[3]);
        $num = unpack("N", $bin);
        return $num[1];
    }

    # Numerisch zu Dezimal
    function inetntoa($num){
        $bin = pack("N", $num);
        $a = unpack("C4", $bin);
        return join(".", $a);    
    }


    function masklenton($masklen){
        if($masklen == 0){ 
            return 0;
        }
        else{
            return(0xffffFFFF <<(32 - $masklen));
        }
    }

    # Bitvergleich von links nach rechts
    # Route Summary
    function bitcmp($ipo){
        $bitcmp = 0;
        foreach( array(31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) as $bit ){
            if( ($this->ipnum >> $bit & 1) == ($ipo->ipnum >> $bit & 1)  ){
                $bitcmp++;  
            }
            else{ 
                break; 
            }
        }
        $this->BITCMP[ $ipo->DATA['IP'] ] = $bitcmp ;
    }

}
###########################################################################

#try{
#    $ipo = new IPv4('10.0.0.0', '255.240.0.0');
#    $ip = new IPv4('127.0.0.0', 8);
#    print_r( $ip );
#}
#catch(Exception $e){
#    die( $e->getMessage() );
#}

Verwendung ohne Gewähr!


Datenschutzerklärung: Diese Seite dient rein privaten Zwecken. Auf den für diese Domäne installierten Seiten werden grundsätzlich keine personenbezogenen Daten erhoben. Das Loggen der Zugriffe mit Ihrer Remote Adresse erfolgt beim Provider soweit das technisch erforderlich ist. s​os­@rolf­rost.de.