summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2011-12-20 01:42:10 +0700
committerDaniil Baturin <daniil@baturin.org>2011-12-20 01:42:10 +0700
commit918231a5ca05fb68dcb73759dedf3dd7293e6c34 (patch)
treed8b30a4093d594fc97330787bf88878aca648bcc
parentf4a499866b75e2175fc1b077950a52c8d0ce02df (diff)
downloadvyos-utils-misc-918231a5ca05fb68dcb73759dedf3dd7293e6c34.tar.gz
vyos-utils-misc-918231a5ca05fb68dcb73759dedf3dd7293e6c34.zip
Quagga to Vyatta converter initial commit.
-rw-r--r--converters/qvconvert.pl409
1 files changed, 409 insertions, 0 deletions
diff --git a/converters/qvconvert.pl b/converters/qvconvert.pl
new file mode 100644
index 0000000..6cd76e0
--- /dev/null
+++ b/converters/qvconvert.pl
@@ -0,0 +1,409 @@
+#! /usr/bin/perl
+
+# Description: Quagga to Vyatta configuration converter
+# Date: May 2011
+# Version: 0.1
+
+# **** MIT License ****
+# Copyright (c) 2011 Daniil Baturin <daniil@baturin.org>
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+# **** End License ****
+
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+# Show help
+sub usage
+{
+ print "Usage:".$0." --config=/path/to/quagga/config\n";
+ print "Options:\n";
+ print " --rule-step=n Step between rule numbers in policy objects (e.g. access-lists)\n";
+ print " --first-rule=n First rule number in policy objects\n";
+ exit(0);
+}
+
+sub trim($)
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
+
+
+# Print help if not one command line argument is given
+if( @ARGV == 0 ) {
+ usage();
+}
+
+# Get options
+my $file;
+my $rule_step = 10; # Default rule step
+my $first_rule = 10; # Default first rule number
+
+GetOptions(
+ "config=s" => \$file,
+ "rule-step=s" => \$rule_step,
+ "first-rule=s" => \$first_rule
+);
+
+# Read configuration file to array
+open(CONFIG, $file) || die("Can not open file: ".$file);
+my @quagga_config = <CONFIG>;
+close(CONFIG);
+
+# Parameters that should be set if found in any line
+my $ip_forwarding = 0;
+my $ipv6_forwarding = 0;
+
+# Rule numbers for access-list processing
+my $acl = 0;
+my $acl_rule = 0;
+
+# Route-map beginning string
+my $rm_begin = '';
+
+foreach(@quagga_config)
+{
+ # Search for "ip route <subnet/mask> <iface|gateway>" statement
+ if( $_ =~ /^ip route/ )
+ {
+ my @words = split( / /, $_ );
+ my $route_command = '';
+
+ if( $words[3] =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ )
+ {
+ # It's an ordinary route
+ $route_command = "set protocols static route ".$words[2]." next-hop ".$words[3];
+ }
+ elsif( $words[3] =~ /Null0/ )
+ {
+ # It's a blackhole route
+ $route_command = "set protocols static route ".$words[2]." blackhole\n";
+ }
+ else
+ {
+ # It's an interface route
+ $route_command = "set protocols static interface-route ".$words[2]." next-hop-interface ".$words[3];
+ }
+
+ if( $words[4] )
+ {
+ # Route has distance
+ $route_command .= " distance ".$words[4];
+ }
+
+ print $route_command;
+ }
+
+ # Search for "ipv6 route <subnet/mask> <iface|gateway>" statement
+ if( $_ =~ /^ipv6 route/ )
+ {
+ my @words = split( / /, $_ );
+ my $route_command = '';
+
+ if( $words[3] =~ /:/ )
+ {
+ # Interface name can not contain ":", thus it's an IPv6 gateway address
+ $route_command = "set protocols static route6 ".$words[2]." next-hop ".$words[3];
+ }
+ elsif( $words[3] =~ /blackhole/ )
+ {
+ # It's a blackhole route
+ $route_command = "set protocols static route6 ".$words[2]." blackhole\n";
+ }
+ else
+ {
+ # Otherwise it's an interface route
+ $route_command = "set protocols static interface-route6 ".$words[2]." next-hop-interface ".$words[3];
+ }
+
+ if( $words[4] )
+ {
+ # Route has distance
+ $route_command .= " distance ".$words[4];
+ }
+
+ print $route_command;
+ }
+
+ # Search for "ip forwarding" statement
+ if( $_ =~ /^ip forwarding/ )
+ {
+ $ip_forwarding = 1;
+ }
+
+ # Search for "ipv6 forwarding" statement
+ if( $_ =~ /^ipv6 forwarding/ )
+ {
+ $ipv6_forwarding = 1;
+ }
+
+ # Search for "ip prefix-list" statement
+ if( $_ =~ /^ip prefix-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ my $pl_begin = "set policy prefix-list ".$words[2]." rule ".$words[4];
+
+ print $pl_begin." action ".$words[5]."\n";
+ print $pl_begin." prefix ".$words[6]."\n";
+ if( $words[7] )
+ {
+ # It has "le" or "ge" statement
+ print $pl_begin." ".$words[7]." ".$words[8];
+ }
+ }
+
+ # Search for "ipv6 prefix-list" statement
+ if( $_ =~ /^ipv6 prefix-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ my $pl_begin = "set policy prefix-list6 ".$words[2]." rule ".$words[4];
+
+ print $pl_begin." action ".$words[5]."\n";
+ print $pl_begin." prefix ".$words[6]."\n";
+ if( $words[7] )
+ {
+ # It has "le" or "ge" statement
+ print $pl_begin." ".$words[7]." ".$words[8];
+ }
+ }
+
+ # Search for "access-list" statement
+ if( $_ =~ /^access-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ if( $acl ne $words[1] )
+ {
+ # Previous access list has ended, reset rule counter
+ $acl_rule = $first_rule;
+ }
+
+ if( $acl_rule > 65535 )
+ {
+ print "Error: access-list rule number exceeded allowed value!\n";
+ print "Try decreasing rule step by using --rule-step=n option";
+ exit(1);
+ }
+
+ $acl = $words[1];
+ my $acl_begin = "set policy access-list ".$acl." rule ";
+
+ print $acl_begin.$acl_rule." action ".$words[2]."\n";
+
+ if( $words[3] ne "ip" )
+ {
+ # It's a standard ACL
+
+ if( $words[3] =~ /any/ )
+ {
+ print $acl_begin.$acl_rule." source ".$words[3]."\n";
+ }
+ elsif( $words[4] )
+ {
+ # ACL has network and inverse mask
+ print $acl_begin.$acl_rule." source network ".$words[3]."\n";
+ print $acl_begin.$acl_rule." source inverse-mask ".$words[4]."\n";
+ }
+ else
+ {
+ # ACL has host only
+ print $acl_begin.$acl_rule." source host ".$words[3]."\n";
+ }
+ }
+ else
+ {
+ # It's an extended ACL
+
+ my $next_word = 0;
+
+ # Get source
+ if( $words[4] =~ /any/ )
+ {
+ print $acl_begin.$acl_rule." source any\n";
+ $next_word = 5;
+ }
+ elsif( $words[4] =~ /host/ )
+ {
+ print $acl_begin.$acl_rule." source host ".$words[5]."\n";
+ $next_word = 6;
+ }
+ else
+ {
+ print $acl_begin.$acl_rule." source network ".$words[4]."\n";
+ print $acl_begin.$acl_rule." source inverse-mask ".$words[5]."\n";
+ $next_word = 6;
+ }
+
+ # Get destination
+ if( $words[$next_word] =~ /any/ )
+ {
+ print $acl_begin.$acl_rule." destination any\n";
+ }
+ elsif( $words[$next_word] =~ /host/ )
+ {
+ print $acl_begin.$acl_rule." destination host ".$words[$next_word+1];
+ }
+ else
+ {
+ print $acl_begin.$acl_rule." destination network ".$words[$next_word]."\n";
+ print $acl_begin.$acl_rule." destination inverse-mask ".$words[$next_word+1]."\n";
+ }
+ }
+
+ $acl_rule += $rule_step;
+ }
+
+ # Search for "ipv6 access-list" statement
+ if( $_ =~ /^ipv6 access-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ if( $acl ne $words[2] )
+ {
+ # Previous ACL has ended, reset rule counter
+ $acl_rule = $first_rule;
+ }
+
+ if( $acl_rule > 65535 )
+ {
+ print "Error: access-list6 rule number exceeded allowed value!\n";
+ print "Try decreasing rule step by using --rule-step=n option";
+ exit(1);
+ }
+
+ $acl = $words[2];
+ my $acl6_begin = "ipv6 access-list ".$acl." rule ";
+
+ print $acl6_begin.$acl_rule." action ".$words[3]."\n";
+
+ if( $words[4] =~ /any/ )
+ {
+ print $acl6_begin.$acl_rule." source any\n";
+ }
+ else
+ {
+ print $acl6_begin.$acl_rule." source network ".$words[4]."\n";
+ }
+
+ if( $words[5] )
+ {
+ print $acl6_begin.$acl_rule." source exact-match\n";
+ }
+
+ $acl_rule += $rule_step;
+ }
+
+ # Search for "ip as-path access-list" statement
+ if( $_ =~ /^ip as-path access-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ if( $acl ne $words[3] )
+ {
+ # Previous ACL has ended, reset rule counter
+ $acl_rule = $first_rule;
+ }
+
+ if( $acl_rule > 65535 )
+ {
+ print "Error: as-path-list rule number exceeded allowed value!\n";
+ print "Try decreasing rule step by using --rule-step=n option";
+ exit(1);
+ }
+
+ $acl = $words[3];
+ my $as_path_begin = "set policy as-path-list ".$acl." rule ";
+
+ print $as_path_begin.$acl_rule." action ".$words[4]."\n";
+ print $as_path_begin.$acl_rule." regex \"".trim($words[5])."\"\n";
+
+ $acl_rule += $rule_step;
+ }
+
+ # Search for "ip community-list" statement
+ if( $_ =~ /^ip community-list/ )
+ {
+ my @words = split( / /, $_ );
+
+ if( $acl ne $words[2] )
+ {
+ # Previous ACL has ended, reset rule counter
+ $acl_rule = $first_rule;
+ }
+
+ if( $acl_rule > 65535 )
+ {
+ print "Error: community-list rule number exceeded allowed value!\n";
+ print "Try decreasing rule step by using --rule-step=n option";
+ exit(1);
+ }
+
+ $acl = $words[2];
+ my $comm_begin = "set policy community-list ".$acl." rule ";
+
+ print $comm_begin.$acl_rule." action ".$words[3]."\n";
+ print $comm_begin.$acl_rule." regex \"".trim($words[4])."\"\n";
+
+ $acl_rule += $rule_step;
+ }
+
+ # Search for "route-map" statement
+ if( $_ =~ /^route-map/ )
+ {
+ my @words = split( / /, $_ );
+
+ $rm_begin = "set policy route-map ".$words[1]." rule ".trim($words[3])." ";
+
+ print $rm_begin."action ".$words[2]."\n";
+ }
+
+ if( trim($_) =~ /^match|on-match|set|call/ )
+ {
+ # It's a line from route-map
+ if( $_ =~ /next-hop/ )
+ {
+ my @words = split( / /, trim($_) );
+ print $rm_begin."set ip-next-hop ".$words[3]."\n";
+ }
+ else
+ {
+ print $rm_begin.$_;
+ }
+ }
+}
+
+
+# If forwarding statements weren't found, forwarding should be disabled
+# (enabled by default in Vyatta)
+if( !$ip_forwarding )
+{
+ print "set system ip disable-forwarding";
+}
+
+if( !$ipv6_forwarding )
+{
+ print "set system ipv6 disable-forwarding";
+}