how to check for ip address that falls inside a range.

M

mike

hi

i need to verify if an ip-address falls inside a range for example,
say 10.1.1.1 to 10.1.2.255.
So if a user keys in 10.1.2.2, it should fall inside this range and
then the program can do something.

How can i go about declaring the range, and how can i check the ip
whether it falls inside the range. ?
thanks.
 
W

Walter Roberson

:i need to verify if an ip-address falls inside a range for example,
:say 10.1.1.1 to 10.1.2.255.
:So if a user keys in 10.1.2.2, it should fall inside this range and
:then the program can do something.

:How can i go about declaring the range, and how can i check the ip
:whether it falls inside the range. ?

for each of the three IP addresses, split the IP address on '\.',
say into @ipd; then
$iaddr = pack('C4', $ipd[0], $ipd[1], $ipd[2], $ipd[3]);
gives the binary equivilent of the IP. Once you have all three,
it's just a matter of testing that the test ip is numerically
between the other two values.
 
G

Gunnar Hjalmarsson

mike said:
i need to verify if an ip-address falls inside a range for example,
say 10.1.1.1 to 10.1.2.255.

One idea:

my $test = '10.1.2.2';
my $lower = '10.1.1.1';
my $higher = '10.1.2.255';

sub iptest {
my @ip = @_;
for ( @ip ) {
$_ = join '', map { sprintf '%03s', $_ } split /\./, $_;
}
$ip[0] >= $ip[1] and $ip[0] <= $ip[2] ? 1 : 0;
}

if ( iptest($test, $lower, $higher) ) {
print "$test falls inside the range $lower to $higher.\n";
}
 
B

Ben Morrow

:i need to verify if an ip-address falls inside a range for example,
:say 10.1.1.1 to 10.1.2.255.
:So if a user keys in 10.1.2.2, it should fall inside this range and
:then the program can do something.

:How can i go about declaring the range, and how can i check the ip
:whether it falls inside the range. ?

for each of the three IP addresses, split the IP address on '\.',
say into @ipd;

Or, better, use Regexp::Common.

Ben
 
T

Tony Curtis

On 29 Jan 2004 18:43:28 -0800,
hi i need to verify if an ip-address falls inside a range
for example, say 10.1.1.1 to 10.1.2.255. So if a user keys
in 10.1.2.2, it should fall inside this range and then the
program can do something.
How can i go about declaring the range, and how can i check
the ip whether it falls inside the range. ? thanks.

http://search.cpan.org/

Take a look at NetAddr::IP and Net::IP::Match, one or both
might do what you want.

hth
t
 
K

Kien Ha

mike said:
hi

i need to verify if an ip-address falls inside a range for example,
say 10.1.1.1 to 10.1.2.255.
So if a user keys in 10.1.2.2, it should fall inside this range and
then the program can do something.

How can i go about declaring the range, and how can i check the ip
whether it falls inside the range. ?
thanks.


#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket qw(inet_aton);


my @ip_range = qw{ 10.1.1.1 10.1.2.255 };
my ($lower, $upper) = map { inet_aton($_) } @ip_range;


for ( qw{ 10.1.2.2 10.1.2.10 10.1.3.222 } ) {
my $packed_ip = inet_aton($_);
if ( $packed_ip lt $lower or $packed_ip gt $upper ) {
print "$_ is out of expected range ",
"$ip_range[0] .. $ip_range[1].\n";
next;
}


print "$_ is in range.\n";
}
 
M

mike

Kien Ha said:
mike said:
hi

i need to verify if an ip-address falls inside a range for example,
say 10.1.1.1 to 10.1.2.255.
So if a user keys in 10.1.2.2, it should fall inside this range and
then the program can do something.

How can i go about declaring the range, and how can i check the ip
whether it falls inside the range. ?
thanks.


#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket qw(inet_aton);


my @ip_range = qw{ 10.1.1.1 10.1.2.255 };
my ($lower, $upper) = map { inet_aton($_) } @ip_range;


for ( qw{ 10.1.2.2 10.1.2.10 10.1.3.222 } ) {
my $packed_ip = inet_aton($_);
if ( $packed_ip lt $lower or $packed_ip gt $upper ) {
print "$_ is out of expected range ",
"$ip_range[0] .. $ip_range[1].\n";
next;
}


print "$_ is in range.\n";
}




Thanks for all the tips...appreciate that..
 
W

Walter Roberson

:> i need to verify if an ip-address falls inside a range for example,

:use IO::Socket qw(inet_aton);

Looking at perldoc, it appears to me that should be Socket instead
of IO::Socket .


: my $packed_ip = inet_aton($_);
: if ( $packed_ip lt $lower or $packed_ip gt $upper ) {

I realized a potential flaw in my pack 'C4' version:
I was using network byte order and numeric comparisions, which
would fail on small-endian or machines with other unusual binary
storage orders. I see that your version avoids that by doing
string comparisons instead of numeric comparisons. Think I'll
go edit some of my code now... ;-)
 
W

Walter Roberson

|In article <[email protected]>,

|: my $packed_ip = inet_aton($_);
|: if ( $packed_ip lt $lower or $packed_ip gt $upper ) {

|I realized a potential flaw in my pack 'C4' version:
|I was using network byte order and numeric comparisions, which
|would fail on small-endian or machines with other unusual binary
|storage orders. I see that your version avoids that by doing
|string comparisons instead of numeric comparisons.

Ah, and I just found a theoretical flaw in the inet_aton version.
The documentation for inet_aton says that it returns an
opaque string, and that one should not assume that it is 32 bits
(e.g., because of IPv6.) Theoretically, then, the results of
inet_aton are not always going to be linear for lt / gt purposes,
even if the inputs are consistantly dotted quads.
 
G

Gunnar Hjalmarsson

Walter said:
Ah, and I just found a theoretical flaw in the inet_aton version.
The documentation for inet_aton says that it returns an opaque
string, and that one should not assume that it is 32 bits (e.g.,
because of IPv6.) Theoretically, then, the results of inet_aton are
not always going to be linear for lt / gt purposes, even if the
inputs are consistantly dotted quads.

So why not keep it simple, then?

http://groups.google.se/[email protected]

;-)
 
W

Walter Roberson

:> Ah, and I just found a theoretical flaw in the inet_aton version.

:So why not keep it simple, then?

:http://groups.google.se/[email protected]

sprintf '%03s' of each quad leads to string comparisons that are
longer than they need be. Not important for a single such test, but
if you are doing many such tests, it could add up. More efficient
string tests can be had by pack()ing each octet as a character.
Looking over some old code last night, I find I have

pack 'C*', split /\./ $_

The question then would be whether conversions from the textual
multi-character octets into binary characters are more efficient
than the sprintf '%03s'. The %03s requires an internal string to
binary conversion as it is (the '3' into the number 3 internally)
and sprintf has a lot of overhead. Possibly more efficient than
either of these would be some manipulations involving substr
and a leading '000' concatenated on...
 
B

Ben Morrow

:> Ah, and I just found a theoretical flaw in the inet_aton version.

:So why not keep it simple, then?

:http://groups.google.se/[email protected]

sprintf '%03s' of each quad leads to string comparisons that are
longer than they need be. Not important for a single such test, but
if you are doing many such tests, it could add up.

Premature optimization is the root of all evil.

Ben
 
G

Gunnar Hjalmarsson

Walter said:
sprintf '%03s' of each quad leads to string comparisons that are
longer than they need be.

That's undoubtedly true.
Not important for a single such test, but if you are doing many
such tests, it could add up. More efficient string tests can be had
by pack()ing each octet as a character. Looking over some old code
last night, I find I have

pack 'C*', split /\./ $_

The question then would be whether conversions from the textual
multi-character octets into binary characters are more efficient
than the sprintf '%03s'.

I made a benchmark (code below), and this is the result:

Rate sprintf pack
sprintf 8035/s -- -46%
pack 14923/s 86% --
The %03s requires an internal string to binary conversion as it is
(the '3' into the number 3 internally) and sprintf has a lot of
overhead.

Seems as if you are right, i.e. using pack() is more efficient.

Here is the benchmarking code:

use Benchmark 'cmpthese';
cmpthese( -5, {
pack => sub {
my @ip = ('10.1.2.2', '10.1.2.255');
for ( @ip ) {
$_ = pack 'C*', split /\./, $_;
}
return 1 if $ip[0] lt $ip[1];
},
sprintf => sub {
my @ip = ('10.1.2.2', '10.1.2.255');
for ( @ip ) {
$_ = join '',
map { sprintf '%03s', $_ } split /\./, $_;
}
return 1 if $ip[0] lt $ip[1];
},
} );
 
W

Walter Roberson

|> (e-mail address removed)-cnrc.gc.ca (Walter Roberson) wrote:
|>> In article <[email protected]>,

|>> for each of the three IP addresses, split the IP address on '\.',
|>> say into @ipd;

|> Or, better, use Regexp::Common.

|Or, perhaps not better, the inet_aton() subroutine in Socket.

We went over that already. Socket::inet_aton() is documented
as producing an opaque structure, and the documentation says one
should not assume the result is 32 bits wide. For example, if your
system supports IPv6, then even though you feed a dotted quad in,
the resulting structure is not certain to be 32 bits wide, and
is not certain to be numerically comparable.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top