Mass IPv4 To IPv6 Converter – Perl

Facing with technology changes day by day. Some of which there is no way we can avoid if we are in the IT industry. The most major problem we would have is the exhaustion of IPv4 address spaces. Once IPv4 address space is exhausted, we would have to use IPv6. For the end user, this is not a very big problem. Due to the simple fact that most ISP will assign IPv6 to the end user automatically when the use of IPv4 become absolutely outdated.

However, for the hosting industry and for those that managed more than thousand of name records, it’s can be a tremendous headache when updating DNS record for each domain name bases on the criteria. How many hours would it take to update thousands of DNS records? How much can we save if the there is a script that can automatically update name records and convert them from IPv4 to IPv6 bases on input?

With that above real life case, we have a programming challenge to solve the problem. This script tutorial which the information from the tutorial can mostly be obtained from within the code itself. It is a lot easier to learn by looking at the example and see it’s in action. For this script, I’m pretty sure that some of us will need its feature or similar in the future. Especially those that are in the hosting industry where you manage a vast amount of DNS records.

What does this script do? This script was written by me in Perl, it read all name record files in a specified directory. You have to configure the extension and the directory to test it. You give the config an IPv4 record and an IPv6 record. It will search through every file in that directory with that naming context one file at a time. The script can then either replace the IPv4 record with an IPv6 record or it can add the IPv6 record to the files. For adding, the program will only add the record if there isn’t another IPv6 record with that is the exact same value within the file(This is to prevent adding records that already exist inside the file.).

The limitation of this currently is that you can only deal with A name record. It will only change one IP at a time. This version is good for anyone who wants or needs to learn from. I will have an update on the script to the version where you can backup the files before changing the value within the file and also you can change multiple records at the same time. When the new version is release, I will also post a copy of it on this blog so please check for update.

To test this script, create a directory with some DNS name records file in it. Create a temp directory, put the configuration into the script. Run the script. I did do some extensive testing on it but if there is a bug, I would like to hear from your comment. Any comment is appreciated. Thank you.

Advertisement

# Copyright notice.
# Written by kevinhng86 @ FAI Hosting Solution.
# A copy of this script can be found on my blog @ http://kevinhng86.iblog.website
# This script follows CDDL-1.0 licensing protocol, to use this script for any purpose you are agreeing to the CDDL-1.0 license.
# CDDL-1.0 license can be found at:
# https://opensmyce.org/licenses/CDDL-1.0

use strict;
package config;
    my $dir = "./config"; # Directory
    my $ext = "test";     # Extension name of the files
    my $ipv4 = "173.208.245.101"; # IPv4 address to look for
    my $ipv6 = "2001:db8:3:4::1"; # IPv6 address to change or replace to
    my $tempdir = "./tmp";        # Temporary directory

package function;
sub getFileList{
    # To use this function, the first argument is directory path, the second argument is the extension name of the file.
    my ($getdir, $getname) = @_; 
    # Array to hold all files with the name ending in the defined extension.
    my @list = ();
    # The output array.
    my @output = (); 
    
    # Open directory and search for all the file with the defined extension.
    # Then compile an array with the name of all file that was found.
    opendir my $DIR,  $getdir or die "Cannot open directory: $!"; 
    @list = grep( /\.$getname$/ ,readdir($DIR));
    closedir($DIR);

    # If the directory name that was inputted doesn't have a "/", then add "/" to the end of it
    if (!($getdir =~ /\/$/)) { $getdir = $getdir . "/";};
    

    # Add full path value to the name of each file that was found then push the result into an output array.
    for (my $i = 0; $i < scalar(@list); $i++){
        my $str = $getdir . @list[$i];
        push @output, $str;
    }
    # This function can return two type of value, the array @list is for filename only or the array @output of which contained file name with full path.
    return @output;
}


sub faiIPv4ToIPv6{
    my ($inarray, $ipv4, $ipv6, $tempdir, $operation) = @_;
    my @filelist = @{ $inarray };
    # Array for storing the information.
    my @repcountarr = ();
    # Has for storing how many records that was replaced from a file.
    my %repcounthash = {};
    # Each time a row is replaced with a record, the count will increase.
    my $repcount = 0; 
    # Temporary file name.
    my $tempfile = "faitemp.tmp";
    # Temporary string to work with, for operation replace.
    my $tempstr = ""; 
    # Temporary sring for operation add
    my $tempstradd = ""; 
    # Variable to check if the temporary directory, pre-exist for script clean up purpose.
    my $tempdirexist = ""; 
    
    # Check operation, only support add or replace
    if ($operation ne "add" && $operation ne "replace"){ 
        die "only support operation add or replace";
    } 
    
    # Create a string with temp file full path, first check to see if there is a splash on the end of temp dir if there is not, add a splash.
    if (!($tempdir =~ /\/$/)){
        $tempdir = $tempdir . "/";
    }
    my $tempfullpath = $tempdir . $tempfile;
    
    
    # Check if temporary directory exist, if it is not, create and set tempdirexist in both case for clean up after. 
    if (-d $tempdir){
        $tempdirexist = "true";
    }
    if (!-d $tempdir){
        $tempdirexist = "false";
        unless(mkdir $tempdir) {
             die "Unable to create $tempdir\n";
        }
    }
    
    if (-e $tempfullpath) {
        die "temporary file $tempfullpath exist.\nYou might have another program use the same name or this script crash while running, check to see if any information is needed\n";
    }
    
    
    for ( my $i = 0; $i < scalar(@filelist); $i++){
        # Set replace count to 0 each time one file is loop through.
        $repcount = 0;
        # Reset all rep count hash property at the start of each loop.
        %repcounthash = {};
        # Read content into this array, each line equal to one array.
        my @content = ();
        # Everytime a newline is read from a file, this count will increase by one for the purpose that the array does not save to the same index everytime.
        my $arrcount = 0;
        # When adding a record, temporary data is saved onto this array.
        my @contentadd = ();
        # Everytime there is a modification to the add array this count would increased.
        my $arraddcount = 0;

        # Open the file and read all the content into an array.
        open(ORGIN, "<"."@filelist[$i]") or die "Could not open file '@filelist[$i]' $!" ;
            while (my $row = <ORGIN>){
                chomp($row);
                @content[$arrcount] = $row;
                $arrcount = $arrcount + 1;
            }
        close(ORGIN);
            
        # For the replacing operation, just replace the IPv4 with IPv6 and replace the single A with the quad AAAA.
        if ($operation eq "replace" ){
            for (my $id = 0; $id < scalar(@content); $id++){
                if ( index(@content[$id], $ipv4) != -1 && index(@content[$id], "A"  ) != -1 ){
                     @content[$id] =~ s/$ipv4/$ipv6/g;
                     @content[$id] =~ s/A/AAAA/g;
                     $repcount = $repcount + 1;
                }
            }
        }
            
        # For an adding operation, check to see if there is the IPv4 value. 
        # If the IPv4 value matched, check to see if whether an IPv6 record exist for that IPv4 record.
        # Only add the IPv6 record if there is not another IPv6 record with the same value exist.
        # Append the information to a difference array so that the records are added right below the original record.
        if ($operation eq "add"){
            for (my $id = 0; $id < scalar(@content); $id++){
                @contentadd[$arraddcount] = @content[$id];
                $arraddcount = $arraddcount + 1;
                if ( index(@content[$id], $ipv4  ) != -1 && index(@content[$id], "A"  ) != -1 ){
                    $tempstr = @content[$id];
                    $tempstr =~ s/$ipv4/$ipv6/g;
                    $tempstr =~ s/A/AAAA/g;
                    if (!(grep { $_ eq $tempstr} @content)){
                        $repcount = $repcount + 1;
                        @contentadd[$arraddcount] = $tempstr;
                        $arraddcount = $arraddcount +1;
                    }
                }
            }
            @content = @contentadd;
        }
           
        # Open a temporary file to write to, then copy the temporary file to the original file that we just read from.
        open(TEMP, ">"."$tempfullpath") or die "Could not open file '$tempfullpath' $!";
            for (my $id = 0; $id < scalar(@content); $id++){
                print TEMP @content[$id] . "\n";
            }
        close( TEMP );
            
        # Replace the original file with a temp file.
        rename ($tempfullpath, @filelist[$i] );

        # Produce a result of how many record was replaced or added in which file.    
        $repcounthash{"operation"} = $operation;
        $repcounthash{"count"} = $repcount;
        $repcounthash{"file"} = @filelist[$i];        
        push @repcountarr, {%repcounthash};
    }
    
    # If the temporary directory was created by this script delete it.
    # If the temporary directory was not created by this script, leave it intact.
    if ($tempdirexist eq "false"){
        rmdir $tempdir;
        if(-e $tempdir){
            print "Temporary directory '$tempdir' could not be deleted";
        }
    }
    return @repcountarr;
}

# The below code is for testing and demonstrating only.
# Replace it's as desire.
package main;

my @test = function::getFileList($config::dir, $config::ext);
my @result = function::faiIPv4ToIPv6([@test], $config::ipv4, $config::ipv6, $config::tempdir, "add");

for (my $i = 0; $i < scalar(@result); $i++){
    if (  @result[$i]->{"operation"} eq "replace"){
    print @result[$i]->{"operation"} . " " . @result[$i]->{"count"} . " record(s) from " . @result[$i]->{"file"} . "\n";
    }
    
    if (  @result[$i]->{"operation"} eq "add"){
    print @result[$i]->{"operation"} . " " . @result[$i]->{"count"} . " record(s) to " . @result[$i]->{"file"} . "\n";
    }
}

This post was written by Kevin and was first post @ http://kevinhng86.iblog.website.
Original Post Name: "Mass IPv4 To IPv6 Converter – Perl".
Original Post Link: http://kevinhng86.iblog.website/2017/01/18/mass-ipv4-to-ipv6-converter-perl/.

Advertisement
directory-software-online-bussiness-script


Random Article You May Like

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*