#!/usr/local/bin/perl5.00502
#
# Copyright (c) 1999, 2000                       RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#------------------------------------------------------------------------------
# Module Header
# Filename          : Asused.pm
# Purpose           : Perl module for asused
# Author            : AA <antony@ripe.net>
# Date              : Dec 1998 
# Description       : functionality of asused in a module
# Language Version  : perl 5.00502 & perl 5.00404
# OSs Tested        : BSDI 3.1
# Command Line      : -
# Input Files       : 
# Output Files      :
# External Programs : 
# Problems          : 
# To Do             : check how to intialize ref to a scalar \$scal type
#                     aggree on policy regarding normalize121 to use 
#                     static IP addresses
# Comments          :
#
# $Id: Asused.pm,v 1.45 2003/07/28 14:22:00 timur Exp $
#------------------------------------------------------------------------------
#fix once RS fix the date problems in DB do strcit check on dates
#To do specify the approveNa in a better way.
#waiting for Ro to update regread functions to include.

package Reg::Asused;

# general Modules

use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

# export stuff
require Exporter;

use Carp;

# To connect to RIPE Whois server
use RipeWhois;  

use Net::RIPEWhois::in qw(
	$STATUS_MISMATCH $MNT_BY_MISMATCH 
        $INVALID_IP4_RANGE $INVALID_DATE 
        $NETNAME_MISMATCH
	);

# Module for manipulation with IPs representations
use ipv4pack;


$VERSION = '1.21';

@ISA = qw(Exporter);
@EXPORT = qw();

# command-line options for whois

my $ALLOCOPT = '-L -T in'; # find all Less specific matches

# I think this is an undocumented feature, so might change in future
# Also used in pcheck.pm
$ALLOCOPT .= " -Vasu$VERSION";     # send the vesrion info whois server 
				   # only works with RIPE whois server 

my $ASSIGNALLOPT = '-M -T in'; # find all More specific matches

# I think this is an undocumented feature, so might change in future
$ASSIGNALLOPT .= " -Vasu$VERSION";

my %default = (
	'VERSION'  => $VERSION,
        'errNo'	   => '', # error no. 
        'errMsg'   => '', # error message 
	'errNoAll' => [], # array of error no.
	'errMsgAll'=> []  # array of error msgs.
        );

#------------------------------------------------------------------------------
# Purpose           : Bless the new progeny 
# Side Effects      : 
# Comments          : 
# IN                : -
# OUT               : -

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my %param = (%default, @_);
    my $self = { %param };
    
    bless $self, $class;
    
    # Make new whois object if necessary
    unless(ref($self->{'Whois'})) {
	# We create an object with stripped comments by default
	my $whois = new RipeWhois('FormatMode' => 1);
	# On error don't create and instance of the class
	return unless($whois);
	# Store the object for farther use
	$self->{'Whois'} = $whois;
    }
    
    return $self;
}

#------------------------------------------------------------------------------
# Purpose           : set/get the error message 
# Side Effects      : 
# Comments          :
# IN                : errorno; errmsg; reset flag
# OUT               : list - (error no.; errmsg)
#
# The errors are stored in list, return value is recent one scalar
# If you need a list access  @{$self->{'errMsgAll'}}, set $debug 

sub error {
  my $self = shift;  

  my($num,  #error no 
     $msg,  #scalar message 
     $reset #reset flag used for resetting list 
     ) = @_; 

    #set error message and number

    #reset the error message and number 
    if($reset){
	$self->{'errNo'} = '';
	$self->{'errMsg'} = '';
    } 
    # We have error code
    elsif($num) {
	$msg ||= '';
	
	$self->{'errNo'} = $num;
	$self->{'errMsg'} = $msg;
      
	#if debug  is used keep a list of errors
	if($self->{'debug'}){
    	    push(@{$self->{'errNoAll'}}, $num);
	    push(@{$self->{'errMsgAll'}}, $msg);
	}
    }
    # else - why did you call me :)?

  return($self->{'errNo'}, $self->{'errMsg'}) if($self->{'errNo'}); #error

  return; #on no errors
}


#-----------------------------------------------------------------------------
# Purpose           : Get the allocation objects from DB
# Side Effects      : 
# Comments          : 
# IN                : ref alloc object, hash of regalloc lines
# OUT               : 0 on success, error code on error, message in $!

sub getDBAlloc {
    my $self = shift;

    my($alloc, $regAllocs) = @_;
    
    my @sortAllocList;  # list of allocation sorted in the of 
                        # @{$regAllocs->{'list'}}

    # Get DB Allocation objects
    my @wList; # warnings in getting alloc object
    
    my %in;    #temp hash used to keep unique list of allocations

    foreach my $rAlloc (@{$regAllocs->{'list'}}) { 
	# Temp alloc object 
        my $tempAlloc = new Net::RIPEWhois::in('Whois' => $self->{'Whois'});
	
	# Netname
        $tempAlloc->validNa($alloc->validNa());
        
        #get list of allocations from DB
        my @inList = $tempAlloc->getIn($rAlloc, $ALLOCOPT);
	
        #validate the list got from DB
        my @allocList = $tempAlloc->validAlloc(@inList);
	
        my($errNo, $errStr) = $tempAlloc->error();

        #check if the errors are mnt-by, status, and na errors
        if((defined($errNo)) && ($errNo == $STATUS_MISMATCH ||
    	    $errNo == $MNT_BY_MISMATCH || $errNo == $NETNAME_MISMATCH)) {
            # ignore this prefix and proceed
            $regAllocs->{$rAlloc}{'error'} .= $errStr;
        }
        #if still error better return
        elsif($errNo) {
            return($errNo, "ERROR: $rAlloc $errStr"); # on error
        }

        #DB returned multiple objects Discard the allocations
        if(scalar(@allocList) > 1){
            my $errMsg = "ERROR: DB returned multiple inetnums as alloc for:\n\t";
            $errMsg .= join("\n\t", @allocList);
            $regAllocs->{$rAlloc}{'error'} = "$errMsg\n";
        }
        
        #found one allocation object
        elsif(@allocList) {
	    my $allocation = $allocList[0];
            #trick to keep unique list in order
            #push allocation object to list  if this object don't exist in %in
            push(@sortAllocList, $allocation) unless($in{$allocation});
            push(@{$in{$allocation}{'query'}}, $rAlloc); #what was prefix
            
            unless ($alloc->{$allocation}){
                $alloc->{$allocation} = $tempAlloc->{$allocation};
            }
            $alloc->{$allocation}{'query'} = $in{$allocation}{'query'};
        } 

        #if no allocations found copy error and proceed with the rest
        else{
            $regAllocs->{$rAlloc}{'error'} .= "No allocation found in DB\n";
        }
    }

    $alloc->{'dbAlloc'} = \@sortAllocList; #keep the list of allocation 
    
    return(undef, @wList); # on success
}

#-----------------------------------------------------------------------------
# Purpose           :  Get all assignments for an allocations  from DB
# Side Effects      : 
# Comments          : 
# IN                : ref to alloc and assign (Net::RIPEWhois::in), 
#                     ref to Net::RIPEWhois
# OUT               : 0 on sucess, error code on error, message in $!

sub getAssign {
    my $self = shift;

    my($alloc,  # ref to alloc
       $assign, # ref to assign
       ) = @_;

    # each allocations found in db
    foreach my $allocation (@{$alloc->{'dbAlloc'}}){ 

        # get list of assignments 
        my @assign = $assign->getIn($allocation, $ASSIGNALLOPT);
	
        my($errNo, $errStr) = $assign->error();

        if(defined($errNo)) { 
            if ($errNo == $INVALID_DATE){
                #invalid date exception till RS correct them
                #if invalid date is found don't proced to checking nw
                $self->{'invaliddate'} = $errStr;
                $assign->error('No', 'errors', 'found'); #reset the error             
            }
	    else {
		 return($errNo, $errStr); # on error 
	    }
        }
        
	# Get only assignments within this allocation
	# XXX: Fix for the bug in Whois DB when unrelated objects
	# returned with -Tin flag.
	@assign = grep 
	    { 
	    (($assign->{$_}{'start'} >= $alloc->{$allocation}{'start'})
	    && ($assign->{$_}{'end'} <= $alloc->{$allocation}{'end'}));
	    }
	    @assign;
	
        # Sort the inetnum by start + end
	# XXX: Larger assignments first
        my @assignSort = sort 
	    {
	    (($assign->{$a}{'start'} <=> $assign->{$b}{'start'})
	    || ($assign->{$b}{'end'} <=> $assign->{$a}{'end'}));
    	    } 
	    @assign;
	
	# Get stastistic on allocation
        $self->stats($alloc, $allocation, $assign, @assignSort);
	
	# Store assignments
        push(@{$assign->{'dbAssign'}}, @assignSort);
	
	# stats calculates free space from the begining of the allocation
	# till the last assignment. Map free space from last assignment 
	# till the end of the allocation.
	if(defined($main::opt{'free'})) {
	    if(@assignSort) {
		my $Abot = $assignSort[0];
		# Find the real bottom of all assignments
		foreach my $asn (@assignSort) {
		    $Abot = $asn if($assign->{$asn}{'end'} > $assign->{$Abot}{'end'});
		}
		
		my $free = $self->findFree($assign->{$Abot}{'end'},
                            ($alloc->{$allocation}{'end'} + 1), $allocation);
		$self->{$allocation}{'sFree'} .= $free if($free);
	    }
            # no assignments, just count the allocation
            else {
                my $free = $self->findFree($alloc->{$allocation}{'start'},
                           $alloc->{$allocation}{'end'}, $allocation);
		$self->{$allocation}{'sFree'} .= $free if($free);
            }
        }
    }
    return; #on success
}

#-----------------------------------------------------------------------------
# Purpose           : count usage, overlap, overlapped usage, classfull assign
# Comments          : 
# in                : ref  to assign, alloc, the sorted list of assign
# out               : undef
sub stats {
    my$self = shift;
    my($alloc,	       # ref alloc Net::RIPEWhois::in
       $allocation,    # inetnum the allocation Net::RIPEWhois::in  
       $assign,        # ref assign Net::RIPEWhois::in
       @assign         # sorted on inetnum list of assignments
       ) = @_;

    my $usage = 0;     # no of IP adresses used
    my $infra = 0;     # no of IP's used for infrastructure
    my $oUsage = 0;    # overlapped usage
    my $oCount = 0;    # overlap count
    my $overlap = 0;   # no of overlaps 
    my $sOverlap = ''; # overlap output formatted string
    my $cCount = 0;    # classfull count no of assignments of size /20 - 24  

    my $i = 0;         # count assignment in this allocation
    
    #initialize the counts and strings
    $self->{$allocation}{'noOfAssigns'} = 0;
    $self->{$allocation}{'paStCount'} = 0;
    $self->{$allocation}{'piStCount'} = 0;
    $self->{$allocation}{'otherStCount'} = 0;
    $self->{$allocation}{'missStCount'} = 0;
    $self->{$allocation}{'sStatus'} = '';
    $self->{$allocation}{'sFree'} = '';  
    $self->{$allocation}{'free'} = 0;
    
    # Calculate boundaries
    my $allocStart = $alloc->{$allocation}{'start'};
    my $allocEnd = $alloc->{$allocation}{'end'};

    # end of previous inetnum
    # just step back one address
    my $prevEnd = $allocStart - 1;

    # look at every inetnum 
    # We assume, that starts of assignments are lined up
    # in asceding order. We not sure about the ends.
    foreach my $in (@assign) {
	# start of inetnum in decimal 
        my $start = $assign->{$in}{'start'};
	# end of inetnum in decimal
        my $end   = $assign->{$in}{'end'};
	# If assignment completely overlappes allocation
	if($start <= $allocStart && $end >= $allocEnd) {
	    push(@{$alloc->{$allocation}{'warning'}}, 
		sprintf("overlapped by %s assignment", $in));
	}	
	# Cut the end of assignment on allocation
	# boundary, if there are errors in assign data.
	$start = $allocStart if($start <= $allocStart);
	$end   = $allocEnd if($end >= $allocEnd);

	# |  1  |
	#----------------
	#        |  2  |
	if($start > $prevEnd){
            #Clean next assignment
            $usage += ($end - $start + 1);
            
            # map the free space if --assign
	    if(defined($main::opt{'free'})) {
		my $free = $self->findFree($prevEnd, $start, $allocation);
		$self->{$allocation}{'sFree'} .= $free if($free);
		}
            $prevEnd = $end;
        }
	# |  1  |
	#-------------
	#     |  2  |
	elsif($end > $prevEnd){
            # An overlapping assignment
            $usage += ($end - $prevEnd);
	    
            $prevEnd = $end;
        }
	# |  1  |
	#---------
	#  | 2 |
        else {
            # ignore
            # print "fully overlapped ones \n";
        }
  
        #usage including overlap 
        $oUsage += $assign->{$in}{'size'};
	
	# infrastructual usage(with overlaps)
	$infra += $assign->{$in}{'size'} if($assign->{$in}{'infra'});
        
        #no of assigments
        $self->{$allocation}{'noOfAssigns'}++;
	
        #count class full assignments 
        $cCount += $self->countClassFull($assign, $in);
	
	# If there are any overlaps
        $oCount += $self->checkOverlap($assign, $i, \@assign, \$sOverlap);

        # format output string if --status, --assign, --infra and count status PI,PA etc
        $self->doStatus($assign, $allocation, $in);
        
        #format string for warnings if any
        foreach (@{$assign->{$in}{'warning'}}) {
            $self->{$allocation}{'warning'} .= sprintf("%s %s\n", $in, $_);
        }
	$i++; #count the assignment used in checking overlap 
    }

    $self->{$allocation}{'usage'} = $usage;
    $self->{$allocation}{'infra'} = $infra;
    $self->{$allocation}{'uOverlap'} = $oUsage;
    $self->{$allocation}{'cOverlap'} = $oCount;
    $self->{$allocation}{'sOverlap'} = $sOverlap;
    $self->{$allocation}{'cClassfull'} = $cCount;
  
    return;  #on success
}

#-----------------------------------------------------------------------------
# Purpose           :  check and count overlaps
# Side Effects      : 
# Comments          : checking done on a square  Matrix of assignmetns [A]nxn 
#                     for i = 0; i < n;
#                       for j= i+1; j < n 
#                          last if start of Aj > end of Ai
#                            check if overlaps Ai with Aj
#         
#                     
# IN                : $i start count in the list
#                     ref to list of assignments
#                     ref to output scalar 
# OUT               : overlap count
sub checkOverlap {
    my $self = shift;

    my($assign,
       $i,          # start count to check overlap
       $assignList, # ref to list of assignments
       $sOverlap    # ref to output scalar 
       ) =@_;

    my $oCount = 0; # no of overlapping assignmenets return value;
       
    # start of first assignment
    my $start = $assign->{$assignList->[$i]}{'start'};
    # end of first assignment
    my $end   = $assign->{$assignList->[$i]}{'end'};
    
    my $j =  $i+1;  #counter on inetnum
    my $jLast = $#{$assignList}; 
    while ($j <= $jLast) {
        
	my $checkStart = $assign->{$assignList->[$j]}{'start'};
	my $checkEnd   = $assign->{$assignList->[$j]}{'end'};

        #skip if inetnum is allready covered.
        last if ($checkStart > $end);

        #it is same inet num
        if(($start == $checkStart) and ($end == $checkEnd)) {
            push(@{$assign->{$assignList->[$i]}{'warning'}},  
            sprintf("inconsitant with %s\n", $assignList->[$j]));
        }

        #check for overlap
        if($start <= $checkEnd && $end >= $checkStart){ 
            #     +*----------x+ start 
            #     |x----------------*+ check 
            $oCount++;

            if(defined($main::opt{'overlap'})){
                #formatted output  for overlap
                $$sOverlap .= sprintf ("OVERLAP %-33s %8d %s\n",
                                       $assignList->[$i],
                                       $assign->{$assignList->[$i]}{'created'},
                                       $assign->{$assignList->[$i]}{'na'}) 
                    if (scalar(@{$assign->{$assignList->[$i]}{'overlap'}}) == 0);
		
                $$sOverlap .= sprintf ("        %-33s %8d %s\n",
                                       $assignList->[$j],
                                       $assign->{$assignList->[$j]}{'created'},
                                       $assign->{$assignList->[$j]}{'na'});
            } 
            #also push list to each inetnum
            push(@{$assign->{$assignList->[$i]}{'overlap'}}, $assignList->[$j]);
            
        }
        $j++;
    }
    return $oCount; #overlap count for this inetnum
}

#-----------------------------------------------------------------------------
# Purpose           :  classfull assign count and usage 
# Side Effects      : 
# Comments          : 
# in                : ref to  $assign, inetnum value, 
#                   : class full usage no of addresses
#                   : no of class full assignments
# out               : class full usage, classfull count

sub countClassFull {
    my $self = shift;

    my($assign, #ref to assign Net::RIPEWhois::in
       $in      #inetnum value 
       ) = @_;
    
    # @{$assign->{'classFullSizes'}} 
    # defined in Net::RIPEWhois::in

    foreach my $size (@{$assign->{'classFullSizes'}}){
	# If assignment is a classfull size, return 1
        return 1 if($size == $assign->{$in}{'size'});
    }
    return 0; # Otherwise
}

#-----------------------------------------------------------------------------
# Purpose           : format the output  string for --status and --assign, 
#		      probably, with --pipa or --infra
# Side Effects      : 
# Comments          : 
# IN                : ref; $assign; $allocation; inetnum value
# OUT               : undef

sub doStatus {
    my $self = shift;
    my($assign, $allocation, $in) = @_;
    
    if($assign->{$in}{'st'}) {
	#status is ASSIGNED PA
	if($assign->{$in}{'st'} =~ /^\s*ASSIGNED\s+PA/i){
    	    $self->{$allocation}{'paStCount'}++;
	    $self->{$allocation}{'sStat'} = 'PA';
            if(defined($main::opt{'assign'})){
	        $self->printStatus($assign, $allocation, $in);
    	    }
	return;    
	} 
        #status ASSIGNED PI
	elsif($assign->{$in}{'st'} =~ /^\s*ASSIGNED\s+PI/i){
	    $self->{$allocation}{'piStCount'}++;
	    $self->{$allocation}{'sStat'} = 'PI';
    	    if(defined($main::opt{'assign'})){
        	$self->printStatus($assign, $allocation, $in);
    	    }
	return;
	}
        #any other status
	elsif($assign->{$in}{'st'}){
    	    $self->{$allocation}{'otherStCount'}++;
	    $self->{$allocation}{'sStat'} = 'UN';
    	    $self->printStatus($assign, $allocation, $in);
	}
    return;
    }
    
    #missing status
    $self->{$allocation}{'missStCount'}++;
    $self->{$allocation}{'sStat'} = '--';
    $self->printStatus($assign, $allocation, $in);
    return;
}

#-----------------------------------------------------------------------------
# Purpose           : print inetnum size, date, netname, staus to scalar
# Side Effects      : 
# Comments          : 
# IN                : ref ref to $assign , allocation , inetnum value
# OUT               : undef

sub printStatus {
    my $self = shift;

    my($assign, $allocation, $in) = @_;
    
    #print inetnum value, size
    $self->{$allocation}{'sStatus'} .= sprintf("%-33s ", $in);
    
    if(defined($main::opt{'cidr'})) {
	$self->{$allocation}{'sStatus'} .= sprintf("%s ", join(',', map { "/$_" } $self->slashed($assign->{$in}{'size'})));
    }
    else {
	$self->{$allocation}{'sStatus'} .= sprintf("%5d ", $assign->{$in}{'size'});
    }
    
    #date of creation
    if($assign->{$in}{'created'}){
	$self->{$allocation}{'sStatus'} .= sprintf("%8d", $assign->{$in}{'created'});
    }
    else {
	$self->{$allocation}{'sStatus'} .= "********";
    }

    # PI/PA
    if(defined($main::opt{'pipa'})) {
	$self->{$allocation}{'sStatus'} .= sprintf(" %-2s", $self->{$allocation}{'sStat'});
    }
    # INFRA-AW
    elsif(defined($main::opt{'infra'})) {
	$self->{$allocation}{'sStatus'} .= sprintf(" %-3s", 
	    ($assign->{$in}{'infra'}) ? ' # ' : ' ');
    }
    
    # NETNAME
    $self->{$allocation}{'sStatus'} .= sprintf(" %-15s ", $assign->{$in}{'na'});
    
    # status
    $self->{$allocation}{'sStatus'} .= $assign->{$in}{'st'} || "<MISSING>" 
        if(defined($main::opt{'status'}) && !defined($main::opt{'pipa'}));
    
    # Infra-aw
    if($assign->{$in}{'infra'}) {
	$self->{$allocation}{'sInfra'} .= sprintf("%-33s %5d ",
						    $in, $assign->{$in}{'size'}); 
        #date of creation
	if($assign->{$in}{'created'}){
	    $self->{$allocation}{'sInfra'} .= sprintf("%8d", $assign->{$in}{'created'});
	}
	else {
	    $self->{$allocation}{'sInfra'} .= "********";
	}
        # NETNAME
        $self->{$allocation}{'sInfra'} .= sprintf(" %-15s ", $assign->{$in}{'na'});
    
	# status
	$self->{$allocation}{'sInfra'} .= $assign->{$in}{'st'} || "<MISSING>" 
    	    if(defined($main::opt{'status'}) && !defined($main::opt{'pipa'}));
	
	$self->{$allocation}{'sInfra'} .= "\n";
    }
    
    $self->{$allocation}{'sStatus'} .= "\n";
        
  return; # on success
}
#-----------------------------------------------------------------------------
# Purpose           : map the free space between two inetnums, format scalar
#                     print prefix notation if can be expressed as single prefix
# Side Effects      : 
# Comments          : 
# IN                : end of the last assignemnet  in decimal
#                     start of the next assignment in decimal
# OUT               : formatted scalar 

sub findFree {
    my $self = shift;
    my($prevEnd,   #end of the last assignemnet 
       $start,     #start of the next assignment 
       $allocation #allocation inetnum
       ) = @_;
    
    my $sFree;	   #return string

    if($start > ($prevEnd + 1)) {
    
        # convert the decimal into range a.b.c.d - p.q.r.s
        my $range = sprintf ("%s - %s", int2quad(($prevEnd + 1)),
            		                int2quad(($start - 1)));
                    
        $sFree = sprintf ("%-33s %6d", $range, $start - $prevEnd - 1);
	$self->{$allocation}{'free'} = 0 unless(defined($self->{$allocation}{'free'}));
        $self->{$allocation}{'free'} += ($start - $prevEnd - 1);
        
        # get the prefix for the free range
        my(@prefixes) = &range2prefixes($range);
	
	# print prefix if it is single prefix
	if(scalar(@prefixes) == 1) {
	    $sFree .= sprintf(" %10s free range", $1) if($prefixes[0] =~ m%(/\d+)$%);
        }

	# Add trailing carriage return
        $sFree .= "\n";
	
      return $sFree;  #on success
    }
    return;
}

# By Oleg
# Has problems with /0
sub slashed {
    my $self = shift;
    my($size) = @_;
    my @prefix = ();
    my $i = 32;
    do {
	push(@prefix, $i) if($size & 1);
	$i--;
    } while($size = $size >> 1);
    return reverse(@prefix);
}

1;
__END__


#  POD for methods that can be called.

=head1 NAME

Reg::Asused - Perl module for asused. 

=head1 SYNOPSIS

  use Reg::Asused;
  use regread;
  use ipv4pack;

  my($asu) = new Reg::Asused;

  my($errNo, $errStr ) = $asu->getDBAlloc($alloc, $whois,  \%regAlloc);
  
  ($errNo, $errStr ) = $asu->getAssign($alloc, $assign, $whois);
  
  ($network, $ret) = $asu->approveNa($whois, $opt{'valid'},  $opt{'regid'});

=head1 DESCRIPTION

=head2 approveNa  

 my ($network, $ret, $vlid) = $asu->approveNa($whois, $arg, $regid); 

Will return ref to inetnum result in string and valid result. On error will return undef. ($errno, $errstr) = $asu->error will return error.


=head2 checkOverlap 

$oCount = $self->checkOverlap($assign, $i, \@assign, \$sOverlap);

Check for overlap in list of inetnum objects.  The list @{$assign->{$assignList->[$i]}{'overlap'}}. have list of overlapping inetnums.

If two inetnums are logically sme will set warning in the list @{$assign->{$assignList->[$i]}{'warning'}}  have list of overlapping inetnums.



=head2 error  

return error number and string. 

($errorno, $errorstr )  = $asu->error;

reset the error $asu->(undef, undef, 1);

=head2 getAssign 

Get all assignments for each  prefix in @{$alloc->{'dbAlloc'}}.

($errNo, $errStr ) = $asu->getAssign($alloc, $assign, $whois);

Return undef on success.

=head2 getDBAlloc

Get allocaions from RIPE whois database for all prefix or allocation under a registary.   C<-L> C<-F> C<-c> C<-T> in . 

check netname same are regid (translated "." "-"), mnt-by is one of valid RIPE maintiner, status is ALLOCATED PA, PI or UNSPECIFIED.

my($errNo, $errStr ) = $asu->getDBAlloc($alloc, $whois,  $regAlloc);

$alloc Ref to Net::RIPEWhois::in
$whois Ref to Net::RIPEWhois 

$regAlloc  ref to hash with keys as queries to locate Allocations.


=head1 AUTHOR

Antony <antony@ripe.net>  software group RIPE NCC <softies@ripe.net>

=head1 SEE ALSO

perl(1).

=cut
