#! /usr/bin/perl

# truncate any zone names and their references to 18 characters when
# upgrading to mendocino. also, truncate firewall name and ipv6-name
# rulesets used in zones to 28 characters. all other firewall usages
# will be truncated to 28 chars in firewall migration script 3-to-4

# see Bug 6292 for more info to understand reason for this migration

use strict;
use warnings;

use lib "/opt/vyatta/share/perl5/";
use XorpConfigParser;
use File::Copy;

my $orig_cfg = shift;
exit 1 unless $orig_cfg;

my $xcp = new XorpConfigParser();
$xcp->parse($orig_cfg);

my $zone_policy = $xcp->get_node( ['zone-policy'] );
exit 0 unless $zone_policy;    # zone-policy not configured

# Enable/disable debug output.
my $DEBUG = undef;

sub dprintf {
  my ($args) = @_;
  if ( defined $DEBUG ) {
    printf( STDERR $args );
  }
}

my $max_zone_length = 23;      # extra 5 chars for 'zone ' or 'from ' at
                               # the front. Thus, check for 18 + 5 = 23

my @zones;
my $zone_policy_children = $zone_policy->{'children'};
foreach my $child (@$zone_policy_children) {

  # Find zone entries
  next unless ( $child->{'name'} =~ /^zone / );
  push @zones, $child;
}

foreach my $zone (@zones) {
  dprintf("\nzone : $zone->{'name'}\n");
  if ( length( $zone->{'name'} ) > $max_zone_length ) {

    my $truncated_zone;
    $truncated_zone = substr( $zone->{'name'}, 0, $max_zone_length );
    $zone->{'name'} = $truncated_zone;
  }
  dprintf("truncated zone : $zone->{'name'}\n");

  # also truncate from zones that are more than 18 chars
  my @from_zones;
  my $zone_children = $zone->{'children'};
  foreach my $child (@$zone_children) {

    # Find from zone entries
    next unless ( $child->{'name'} =~ /^from / );
    push @from_zones, $child;
  }
  foreach my $from_zone (@from_zones) {
    dprintf("\tfrom zone : $from_zone->{'name'}\n");
    if ( length( $from_zone->{'name'} ) > $max_zone_length ) {

      my $truncated_from_zone;
      $truncated_from_zone =
        substr( $from_zone->{'name'}, 0, $max_zone_length );
      $from_zone->{'name'} = $truncated_from_zone;
    }
    dprintf("\ttruncated from zone : $from_zone->{'name'}\n");

    # also, since we're traversing the zone tree here, we'll truncate any
    # firewall ruleset names being used in zone tree to be make them less than
    # or equal to 28 characters. all other firewall ruleset instances will
    # be truncated in firewall's 3-to-4 migration script
    my $FW = $xcp->get_node(
      [ 'zone-policy', $zone->{'name'}, $from_zone->{'name'}, 'firewall' ] );
    if ( defined($FW) ) {
      my $childrenFW = $FW->{'children'};
      if ( defined($childrenFW) ) {
        foreach my $hashFWnodes (@$childrenFW) {
          if ( $hashFWnodes->{'name'} =~ /^name.*/ ) {
            dprintf("\t\tipv4 firewall : $hashFWnodes->{'name'}\n");
            if ( length( $hashFWnodes->{'name'} ) > 33 ) {

              # extra 5 chars for 'name ' at the front
              my $truncated_fw = substr( $hashFWnodes->{'name'}, 0, 33 );
              $hashFWnodes->{'name'} = $truncated_fw;
            }
            dprintf("\t\ttruncated ipv4 firewall : $hashFWnodes->{'name'}\n");
          }
          if ( $hashFWnodes->{'name'} =~ /^ipv6-name.*/ ) {
            dprintf("\t\tipv6 firewall : $hashFWnodes->{'name'}\n");
            if ( length( $hashFWnodes->{'name'} ) > 38 ) {

              # extra 10 chars for 'ipv6-name ' at the front
              my $truncated_ipv6_fw = substr( $hashFWnodes->{'name'}, 0, 38 );
              $hashFWnodes->{'name'} = $truncated_ipv6_fw;
            }
            dprintf("\t\ttruncated ipv6 firewall : $hashFWnodes->{'name'}\n");
          }
        }
      }
    }    # end of firewall ruleset truncation 'if (defined($FW))'
  }    # end of from zones truncation loop
}    # end of zone name truncation loop

my $tmpname = "/tmp/vyatta_migrate_zone_policy.$$";
open( my $tmp, '>', $tmpname )
  or die "Can't open: $tmpname: $!";

select $tmp;
$xcp->output(0);
select STDOUT;
close $tmp;

move( $tmpname, $orig_cfg )
  or die "Move $tmpname to $orig_cfg failed: $!";
