IPリストを固定ネットワークCIDR形式に変換するためのツールはありますかx.x.x.0/24
?x.x.0.0/16
たとえば、これを実証するために、次のように固定形式に変換できるIPのリストがあります。
まず、次のIPリストを可能なCIDR 24に変換したいが固定フォーマットに変換したい場合x.x.x.0/24
:
./list2cidr 24 iplist.txt
1.22.3.4
1.28.3.5
1.211.3.7
1.211.3.2
1.211.3.1
Output:
1.22.3.4
1.28.3.5
1.211.3.0/24
どのように動作しますか?
まず、同じネットワーク上のIPリストをスキャンし、同じネットワーク上にある場合は、3番目のオクテットを調べてそれらを組み合わせますx.x.x.0/24
。この例では、3番目のオクテットに同じネットワークを持つ3つのIPがあります。
1.211.3.7
1.211.3.2
1.211.3.1
だからこれは次のようになります:1.211.3.0/24
別の例として、次のIPリストを可能なCIDR 16に変換したい場合は、固定形式は次のようになりますx.x.0.0/16
。
./list2cidr 16 iplist.txt
1.1.4.1
1.1.4.2
1.22.44.1
1.22.3.2
1.22.1.9
Output:
1.1.0.0/16
1.22.0.0/16
これを含むパラメータを渡すと、16
2番目のオクテットが同じネットワーク上にあることが確認されます。x.x.0.0/16
これに対してスクリプトの作成を開始する必要がありますか?それともこの目的のためのツールはありますか?
編集する:
CIDRフォームを次のいずれかのように作成したいと思います。1.1.1.0/24
と1.1.0.0/16
。だから1.1.0.0/24
まだ1.1.1.0/16
私が望むものではありません。
これは、渡された場合はlist2cidr 24 iplist.txt
次の出力を形成する必要があることを意味します。
x.x.x.0/24
パスすると、list2cidr 16 iplist.txt
次の出力が形成されるはずです。
x.x.0.0/16
私は現在bashスクリプトを使用して出力の最初の部分を実行しましたが、まだ完全にテストしていません。
答え1
私は知らなかったので(Perlで)1つ書きました。私もあなたのツールデザインが不完全だと思います。
- アドレスが1つしかない場合でも、要求されたレベルのCIDRブロックのみを提供する必要があります。
- また、目標レベルなしで動作する必要があります。
したがって:
$ cat sample
1.22.3.4
1.28.3.5
1.211.3.7
1.211.3.2
1.211.3.1
$ list2cidr 24 sample
1.22.3.0/24
1.28.3.0/24
1.211.3.0/24
$ list2cidr 16 sample
1.22.0.0/16
1.28.0.0/16
1.211.0.0/16
$ list2cidr sample
1.0.0.0/8
1.16.0.0/12
1.22.3.4
1.28.3.5
1.211.3.0/29
1.211.3.0/30
1.211.3.1
1.211.3.2
1.211.3.7
$
現在の実装ではIPv4のみをサポートしています。コードは次のとおりです
#!/usr/bin/perl -w
use strict;
my $target;
if ($ARGV[0] =~ m{^\d+}) {
$target = + shift @ARGV;
}
my $map = [];
sub record($)
{
my $v = shift;
my $m = $map;
for my $i ( 0 .. 31 ) {
my $k = $v & (1 << (31-$i));
$m = $m->[!!$k] ||= (($i == 31) ? $v : []);
}
}
while (<>) {
chomp;
if (m{^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*\z}) {
if (($1 < 256) && ($2 < 256) && ($3 < 256) && ($4 < 256)) {
record(($1<<24) | ($2<<16) | ($3 << 8) | $4);
next;
}
}
printf("Invalid: %s\n", $_);
}
sub output($$$) {
my ($addr, $bits, $indent) = @_;
printf "%*s%d.%d.%d.%d",
$indent*4, '',
0xff & ($addr >> 24),
0xff & ($addr >> 16),
0xff & ($addr >> 8),
0xff & ($addr );
printf("/%d", $bits) if $bits < 32;
print "\n";
}
sub walk($$$$);
sub walk($$$$) {
my ($prefix, $bits, $indent, $m) = @_;
#printf ("%d %d %d ...\n", $prefix, $bits, $indent);
if ($bits == ($target//-1)) {
output $prefix<<(32-$bits), $bits, 0;
} elsif ($bits == 32) {
warn 'mismatch '.$prefix.' != '.$m unless $prefix == $m;
output $prefix, $bits, $indent unless defined $target;
} elsif (defined $m->[0]) {
if (defined $m->[1]) {
output $prefix<<(32-$bits), $bits, $indent unless defined $target;
walk($prefix*2, $bits+1, $indent+1, $m->[0]);
walk($prefix*2+1, $bits+1, $indent+1, $m->[1]);
} else {
walk($prefix*2, $bits+1, $indent, $m->[0]);
}
} else {
if (defined $m->[1]) {
walk($prefix*2+1, $bits+1, $indent, $m->[1]);
} else {
warn sprintf('Empty node at prefix=%x bits=%d indent=%d', $prefix, $bits, $indent);
}
}
}
walk (0, 0, 0, $map);
答え2
以下はコマンドラインユーティリティを使用しますipcalc
(https://github.com/pyr/ipcalcfile
)は、与えられたネットワークマスクと呼ばれるファイルに与えられた各アドレスのネットワークアドレスを計算します$mask
。
xargs -I {} ipcalc {} / "$mask" <file |
awk -F: '$1 ~ /^network/ && !seen[$2]++ { gsub(" ","",$2); print $2 }'
最後に、出力をawk
解析し、一意のネットワークアドレスを抽出します。ipcalc
サンプルデータが与えられたら、これを実行するとmask=24
次のようになります。
1.22.3.0/24
1.28.3.0/24
1.211.3.0/24
そしてmask=12
:
1.16.0.0/12
1.208.0.0/12
少し変更すると、Ubuntuでipcalc
このパッケージを使用できます。ipcalc
xargs -I {} ipcalc -b {}/"$mask" <file |
awk -F: '$1 ~ /^Network/ && !seen[$2]++ { gsub(" ","",$2); print $2 }'