2016-07-14 9 views
0

Ich habe eine IP mit Subnetzmaske und möchte eine Tabelle erstellen, in der jede Zeile eine IP ist.Finden Sie alle IPs von Subnetz in Perl

Art wie folgt aus:

IP   | MAC | Alive 
192.168.1.1 | ... | yes 
192.168.1.2 | ... | no 
192.168.1.3 | ... | yes 
... 

Für einen Bereich mit Subnetz/24, ist dies einfach, da ich eine for-Schleife 0-254 erzeugen kann, aber ich habe Probleme mit der Tabelle mit einer Erzeugungs/21 Subnetz. Gibt es eine Möglichkeit, in Perl herauszufinden, was der minimale Host, der maximale Host und alles dazwischen ist?

Ich habe das Net::IP und das NetAddr::IP Modul überprüft, aber scheinen keine Lösung für mein Problem. Allerdings bin ich ein Perl-Neuling, also könnte es sein, dass ich es übersehen habe.

edit: gefunden, wie erste und letzte Adresse zu finden:

my $range = "IP/subnet" ; 
my $ip = new Net::IP ($range) || die; 
print $ip->ip(), "\n"; 
print $ip->last_ip(), "\n"; 

Jetzt muss ich in die IP-Adressen finden zwischen

Antwort

2

Die Dokumentation für Net::IP hat ein Beispiel dafür, wie man dies im looping Abschnitt tut.

Demo:

use Net::IP; 

my $ip = new Net::IP("192.168.42.16/28"); 
do { 
    print $ip->ip(), "\n"; 
} while (++$ip); 
192.168.42.16 
192.168.42.17 
192.168.42.18 
192.168.42.19 
192.168.42.20 
192.168.42.21 
192.168.42.22 
192.168.42.23 
192.168.42.24 
192.168.42.25 
192.168.42.26 
192.168.42.27 
192.168.42.28 
192.168.42.29 
192.168.42.30 
192.168.42.31 

Wenn Sie nur eine IP-im gewünschten Bereich haben, nicht das Präfix, können Sie das Präfix von der Adresse und Netmask berechnen. Versuchen Sie so etwas wie diese (es wahrscheinlich ist ein cleverer Weg, dies allerdings mit Net::IP zu erreichen, aber das ist mir eluding):

use Net::IP; 

my $addr = "192.168.42.23"; 
my $len = 28; 

my $mid = new Net::IP($addr, 4); 
my $mask = Net::IP::ip_get_mask($len, 4); 
my $first = $mid->binip() & $mask; 
my $ip = new Net::IP(Net::IP::ip_bintoip($first, 4)."/$len", 4); 
do { 
    print $ip->ip(), "\n"; 
} while (++$ip); 
+0

gefunden Nur, dass auch und versuchte, aber es funktioniert nur für mich, wenn ich das Subnetz verwenden Adresse. Es scheint, dass ich das wissen muss und die erste Adresse nicht verwenden kann. So funktioniert es mit '192.168.0.0/21' und' 192.168.0/21', aber nicht mit '192.168.0.1/21'. Letzteres wird nach der Instantiierung "undef" zurückgeben. – simbabque

+0

Es wurde eine Möglichkeit hinzugefügt, diese Subnetzadresse von einer beliebigen Adresse im Bereich abzurufen. Nicht schön, ich habe irgendwie eine Funktion erwartet, die genau das tut, aber sie nicht finden kann ... – Mat

3

Sie tun können, mit NetAddr::IP dass und dem nth method. Ich habe einen Hilfssub erstellt, der einen Singleton verwendet, um einen Iterator zu erstellen. Sie geben eine beliebige IP-Adresse aus dem Subnetz ein und erhalten eine Codereferenz, mit der Sie das nächste IP-Adressobjekt empfangen können. Dies wird so lange gemacht, bis der Bereich erschöpft ist. An diesem Punkt wird undef zurückgegeben.

use strict; 
use warnings 'all'; 
use NetAddr::IP; 
use feature 'say'; 

sub make_ip_iterator { 
    my $ip = shift; 

    my $mask = NetAddr::IP->new($ip); 

    my $i = 0; 
    return sub { 
     return $mask->nth($i++); 
    } 
} 

my $iterator = make_ip_iterator('192.168.1.1/21'); 
while (my $ip = $iterator->()) { 
    say $ip; 
} 

Da $mask und $i im make_ip_iterator Unter lexikalischer sind, können Sie es mehrmals aufrufen und verschiedene Iteratoren zurück für verschiedene Subnetze, die Sie zur gleichen Zeit nutzen.

Man könnte es natürlich implementieren mit nur einer while Schleife und eine Zählvariable, weil nth() wird undef zurück, wenn es mit einem Index außerhalb des Subnetzes, aber diese Lösung ist mehr tragbar genannt wird.