当然ながら設定のコンバータなんてものはありませんので設定移行は手作業にならざるを得ません。しかし、いくらなんでも1000行以上あるACL等を数カ所分手作業で移行するのがベストとは思いませんでしたので、今回はコンバータを作成することにしました。
(プラス、検証や構築で忙しかったのですが・・・)
んでもって、今回ですが
旧装置→IPアドレスをレンジで指定する
新装置→IPアドレスをサブネットで指定する
という特徴があって、、、
その部分をいかに最適化できるかという事をやってみたのですが。
#IPアドレス範囲をサブネットで最適化して数値リストに変換する
sub range2val ($$$\@) {
my ($range_start, $range_end, $bits, $list) = @_;
my @addr;
my $buf;
my $ipaddr;
if($range_start > $range_end) {
return;
};
if($bits < 0 || $bits > 32) {
return;
};
if(&val2net($range_start, $bits) == $range_start
&& &val2broadcast($range_start, $bits) <= $range_end) {
push(@$list, sprintf("%s/%d", $range_start, $bits));
&range2val(&val2broadcast($range_start, $bits) + 1, $range_end, 0, $list);
return;
} else {
&range2val($range_start, $range_end, $bits + 1, $list);
return;
};
};
#-----------------------------------------------------------
#数値からネットワークアドレスを求める
sub val2net ($$) {
my ($addr, $bits) = @_;
my $buf = substr(&val2bin($addr), 0, $bits);
$buf .= "0" x 32;
$buf = substr($buf, 0, 32);
my @addrval = unpack("H2H2H2H2", pack("B*", $buf));
return hex(join('', @addrval));
};
#-----------------------------------------------------------
#数値からブロードキャストアドレスを求める
sub val2broadcast ($$) {
my ($addr, $bits) = @_;
my $buf = substr(&val2bin($addr), 0, $bits);
$buf .= "1" x 32;
$buf = substr($buf, 0, 32);
my @addrval = unpack("H2H2H2H2", pack("B*", $buf));
return hex(join('', @addrval));
};
#-----------------------------------------------------------
#数値から2進数の文字列を求める
sub val2bin () {
my ($val) = @_;
my $binval = sprintf("%s%s%s%s",
unpack("B8", chr(($val >> 24) & 0xff)),
unpack("B8", chr(($val >> 16) & 0xff)),
unpack("B8", chr(($val >> 8) & 0xff)),
unpack("B8", chr($val & 0xff)));
return $binval;
};
こんな感じで。美しいとか、Perlらしいとか、そういうコードではありませんけど、汎用性の少ないこれっきりのコードであれば、別に今使えればいいだけですので、動けばOKというスタンスです。(ここに挙げた2進数というか、こういう処理って本来Perlの得意分野ではありませんけど、、、実は別の部分で旧装置のコンフィグをテキストで読んできて、データ化して、最適化して新装置用にはき出す・・・という事をやってますので、そういう意味ではPerlの得意分野になります)
ポイントはIPアドレスを一意の整数(32ビット長)として扱う事でしょうか?
もう一つは、レンジからできる限りサマライズされたサブネットを得る部分の処理が思いっきり再帰な部分ですかね。
コメント