arpan shah
arpan shah

Reputation: 277

IP address conditional statement in perl

We have a one Perl script in our system which authenticate the IP address from our group. The script was developed by a previous developer and I am not fluent in Perl. We have a set of IPs which are hard coded and check before it perform an operation. Here is the code snippet(example):

unless ($remoteip eq "some ip" || $remoteip eq "some IP" || $remoteip eq   "xx.xx.xx.xx" )

Now I want to add another 50 IP addresses which are in range (xx.xx.xx.145 to xx.xx.xx.204) I don't want to add each of them one by one in Unless statement because that will be lengthy and not good to programing (I think). Is there any way I can add a "Less than" or "greater than" statement for IP address? Something like Unless($remoteip <="xx.xx.xx.204" AND $remoteip >= "xx.xx.xx.145").

Thanks.

Upvotes: 1

Views: 414

Answers (3)

Josh Goldberg
Josh Goldberg

Reputation: 121

Convert the quad to an 32-bit integer and you're set. There are some modules on CPAN that will do it for you but it boils down to something like this

sub ip2dec ($) {
    unpack N => pack CCCC => split /\./ => shift;
}

if (ip2dec($remoteip) <= ip2dec('xx.xx.xx.204') && ip2dec($remoteip) >= ip2dec('xx.xx.xx.145')) {
   # do something
}

For example 111.222.233.244 is converted to 1876879860 (0x6fdee9f4, 01101111110111101110100111110100). So you can not only compare (order) addresses, but you can also apply bit masks to it.

Upvotes: 2

oalders
oalders

Reputation: 5279

It's not a big deal to handle the logic yourself, but as has been pointed out, there are also CPAN modules to do this for you. I've shortened the length of your range for brevity of output in this case:

use strict;
use warnings;
use feature qw( say );

use Net::Works::Address;

my $lower = Net::Works::Address->new_from_string( string => '10.0.0.145' );
my $upper = Net::Works::Address->new_from_string( string => '10.0.0.150' );

foreach my $i ( 0 .. 255 ) {
    my $ip   = '10.0.0.' . $i;
    my $auth = check_ip( $ip );
    say "$ip is OK" if $auth;
}

sub check_ip {
    my $ip = shift;
    my $address = Net::Works::Address->new_from_string( string => $ip );
    return ( $address <= $upper && $address >= $lower );
}

Output is:

10.0.0.145 is ok
10.0.0.146 is ok
10.0.0.147 is ok
10.0.0.148 is ok
10.0.0.149 is ok
10.0.0.150 is ok

Upvotes: 0

salparadise
salparadise

Reputation: 5805

You can use the Socket module with the inet_aton method and covert a range into an array and grep through that.

use v5.16;
use strict;
use warnings;
use Socket qw/inet_aton/;
#using 10.210.14 as the first three octects
#convert range into binary
my @addressrange = map {unpack('N',inet_aton("10.210.14.$_"))} (145..204);
#address to test
my $address = $ARGV[0];
#grep for this binary in the range
unless(grep {unpack('N',inet_aton($address)) eq $_} @addressrange) {
  say "Address not part of the range"
}
else {
  say "Address is part of the range"
}

And then to run

perl iphelp.pl 10.210.14.15
Address not part of the range

perl iphelp.pl 10.210.14.145
Address is part of the range

Upvotes: 0

Related Questions