Bash
將 IP 列表轉換為固定 CIDR 形式
x.x.x.0/24
有沒有一種工具可以用和將 IP 列表轉換為固定網路 CIDR 形式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
它的參數時,如果它們在同一個網路中,它將查看第二個八位字節,所以我們將它組合成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
不是我想要的。這意味著,如果 pass
list2cidr 24 iplist.txt
,它必須形成這個輸出
x.x.x.0/24
如果我通過
list2cidr 16 iplist.txt
,它必須形成這個輸出
x.x.0.0/16
目前,我已經使用 bash 腳本完成了輸出的第一部分,但我還沒有完全測試它
我不知道,所以我寫了一個(在 perl 中)。我還認為您的工具設計不完整。
- 它應該只給出所請求級別的 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);