Search IP Address in list of ranges -- not working great

I have been struggling with a script to automate some security related activities. I have it pretty much working, all except the search. I have an input file formatted as such:

216.234.246.158    216.234.246.158    `[Spyware_Sites]`
        
24.249.221.22    24.249.221.200    `[Spyware_Sites]`
        
24.249.226.0    24.249.226.255    `[Spyware_Sites]`
        
24.23.0.0    24.30.255.255    `[Spyware_Sites]`
        
64.14.90.11    64.14.97.255    `[Spyware_Sites]`
        
64.128.107.0    64.128.107.255    `[Spyware_Sites]`
        
64.60.0.0    64.62.255.255    `[Spyware_Sites]`
        
64.62.133.6    64.62.133.6    `[Spyware_Sites]`

This represents ranges of IP addresses that have been defined in a security appliance. I need to search this file to determine if the input variable (An single IP Address) falls within any of these ranges. If so display the line.

I am a a novice at development, and naively though this would be fairly straight-forward. It wasn't. However, after many false starts, I was able to get some fairly accurate (fuzzy) results by iteratively searching the first octect for an exact match>file, then using agrep -B to find the best match from there. My code:

echo $1 >htmp1.tmp
cut -f 1 -d "." htmp1.tmp >htmp2.tmp
var1=$(cat htmp2.tmp)
grep -E ''"^$var1"'\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' hgworking.txt >htmp3.tmp
agrep -B -y $1 htmp3.tmp

This is not ideal, but works for now. I am new to programming -- surely there are folks out there that help me produce more exact results. Thanks in advance!

  • Kevin

Input and output are blue-coloured.

[root@hostname dir]# perl -lane '$x="64.61.1.1"; $x = join ("", (map {sprintf "%03d", $_} (split/\./,$x)));
$ip1 = join ("", (map {sprintf "%03d", $_} (split/\./,$F[0])));
$ip2 = join ("", (map {sprintf "%03d", $_} (split/\./,$F[1])));
($x >= $ip1 && $x <=$ip2) && print' inputfile
64.60.0.0    64.62.255.255    `[Spyware_Sites]`
1 Like

An awk based solution along the same lines as the perl posted by balajesuri.
Searches for IP address passed in as $1 to the script. Optionally pass in the file to search, or redirect it in from stdin.

#!/usr/bin/env ksh

grep ${1%%.*} $2 | awk -v target=$1 '
    function toi( str,  a )
    {
        split( str, a, "." );
        return sprintf( "%d%03d%03d%03d", a[1], a[2], a[3], a[4] ) +0;
    }

    BEGIN { tvalue = toi( target ); }

    NF > 1 {
        if( tvalue >= toi( $1 )  &&   tvalue <= toi( $2 ) )
        {
            matched = $0;
            exit( 0 );
        }
    }
    END {
        if( matched )
            printf( "%s is in range: %s\n", target, $0 );
        else
            printf( "%s is OK\n", target );
    }
'

And before any flames are thrown about not needing the grep... No, it's not needed, but I assume it's faster to let awk munge a subset of the input rather than munging the whole input list.

1 Like

Agama, this solution worked perfectly!

This input file is thousands of lines long... So i agree with you the iterative search should significantly improve performance.

Really appreciate everyone's help!

$ awk -F'[ \t.]*' '{split(ip,IP); for(i=1;i<=4;i++) if($i>IP || $(i+4)<IP) next}1' ip=24.25.1.1  infile
24.23.0.0    24.30.255.255    `[Spyware_Sites]`