Discussion:
ISINNET Function (or similar)
(too old to reply)
Antgoodlife
2008-12-30 19:40:19 UTC
Permalink
New to perl and this community...Hi all...

I've done some javascript / proxy pac work and I was curious if perl
has a built in (or if someone can point me to a module) that
determines if an IP is in a specific network? (Similar to proxy.pac
isinnet function)

For example :

#!/usr/bin/perl -w
# if ip 10.8.5.3 is in net 10.8.0.0 w/mask 255.255.0.0 return true
$ipaddr = "10.8.5.3"
print "$ipaddr is in the network!" if isinnet
($ipaddr,"10.8.0.0","255.255.0.0");

CIDR notation acceptance is a plus however not required for my
question.

Thank you in advance.
Klaus
2008-12-30 19:57:58 UTC
Permalink
... (or if someone can point me to a module) that
determines if an IP is in a specific network?  (Similar to proxy.pac
isinnet function)
I have found the following as the second link in a Google search:
("isinnet cpan")
http://search.cpan.org/src/MIYAGAWA/HTTP-ProxyPAC-0.01/lib/HTTP/ProxyPAC/Functions.pm

--
Klaus
Antgoodlife
2008-12-30 21:49:24 UTC
Permalink
Thank you Klaus, I actually found that but was unable to get it
working.. thus headed to the forums... any idea what I can be doing
wrong?
On a Win32 box running Perl 5.10.0

Ran : ppm install HTTP-ProxyAutoConfig

Then :
C:\>type TestInNet.pl
#!/usr/bin/perl -w
# if ip 10.16.5.3 is in net 10.16.0.0 w/mask 255.255.0.0 return true
use HTTP::ProxyAutoConfig;

$ipaddr = "10.16.5.3";

if isInNet($ipaddr,"10.16.0.0","255.255.0.0"); {
print "$ipaddr is in the network!";
}

C:\>TestInNet.pl
Useless use of a constant in void context at C:/Perl/site/lib/HTTP/
ProxyAutoConfig.pm line 367.
syntax error at C:\TestInNet.pl line 7, near "if isInNet"
Execution of C:\TestInNet.pl aborted due to compilation errors.
... (or if someone can point me to a module) that
determines if an IP is in a specific network?  (Similar to proxy.pac
isinnet function)
("isinnet cpan")http://search.cpan.org/src/MIYAGAWA/HTTP-ProxyPAC-0.01/lib/HTTP/Proxy...
--
Klaus
Antgoodlife
2008-12-30 21:52:27 UTC
Permalink
!! Sorry... modified for the post too quickly w/out proper syntax... I
mean I get "THIS error"
C:\>TestInNet.pl
Useless use of a constant in void context at C:/Perl/site/lib/HTTP/
ProxyAutoConfig.pm line 367.
Undefined subroutine &main::isInNet called at C:\TestInNet.pl line 7.

C:\>type TestInNet.pl
#!/usr/bin/perl -w
# if ip 10.16.5.3 is in net 10.16.0.0 w/mask 255.255.0.0 return true
use HTTP::ProxyAutoConfig;
$ipaddr = "10.16.5.3";

if (isInNet($ipaddr,"10.16.0.0","255.255.0.0")) {
print "$ipaddr is in the network!";
}
Mirco Wahab
2008-12-30 22:23:37 UTC
Permalink
Post by Antgoodlife
!! Sorry... modified for the post too quickly w/out proper syntax... I
mean I get "THIS error"
C:\>TestInNet.pl
Useless use of a constant in void context at C:/Perl/site/lib/HTTP/
ProxyAutoConfig.pm line 367.
Undefined subroutine &main::isInNet called at C:\TestInNet.pl line 7.
C:\>type TestInNet.pl
#!/usr/bin/perl -w
# if ip 10.16.5.3 is in net 10.16.0.0 w/mask 255.255.0.0 return true
use HTTP::ProxyAutoConfig;
$ipaddr = "10.16.5.3";
if (isInNet($ipaddr,"10.16.0.0","255.255.0.0")) {
print "$ipaddr is in the network!";
}
I don't know what the module is supposed to do,
but wouldn't a simple comparison of fields against
the netmask:


...

my $net = '10.16.0.0';
my $mask = '255.255.0.0';

my $ip = "10.16.5.3";

if( isInNet($ip, $net, $mask) ) {
print 'true'
}
else {
print 'false'
}

sub isInNet {
my @ip = split /\./, $_[0]; # split ip into net fields
my @net = split /\./, $_[1]; # split network into fields
for( $_[2] =~ /255/g ) { # iterate over '255' mask fields
return 0 if shift(@ip) ne shift(@net) # bail if different
}
1
}

...



suffice? Of course, only for IPV4.

Regards

M.
Hans Mulder
2008-12-31 00:35:54 UTC
Permalink
Post by Mirco Wahab
Post by Antgoodlife
!! Sorry... modified for the post too quickly w/out proper syntax... I
mean I get "THIS error"
C:\>TestInNet.pl
Useless use of a constant in void context at C:/Perl/site/lib/HTTP/
ProxyAutoConfig.pm line 367.
Undefined subroutine &main::isInNet called at C:\TestInNet.pl line 7.
C:\>type TestInNet.pl
#!/usr/bin/perl -w
# if ip 10.16.5.3 is in net 10.16.0.0 w/mask 255.255.0.0 return true
use HTTP::ProxyAutoConfig;
$ipaddr = "10.16.5.3";
if (isInNet($ipaddr,"10.16.0.0","255.255.0.0")) {
print "$ipaddr is in the network!";
}
I don't know what the module is supposed to do,
but wouldn't a simple comparison of fields against
...
my $net = '10.16.0.0';
my $mask = '255.255.0.0';
my $ip = "10.16.5.3";
if( isInNet($ip, $net, $mask) ) {
print 'true'
}
else {
print 'false'
}
sub isInNet {
for( $_[2] =~ /255/g ) { # iterate over '255' mask fields
}
1
}
...
suffice? Of course, only for IPV4.
That worked in the early days when the only numbers allowed in a netmask
were 0 and 255. In 1993 the rules changed. Today netmasks can also
contain 128, 192, 224, 240, 248, 252 and 254.

One way to check that a network contains an IP addres is to convert all
three numbers to binary. If the bitwise "and" of the IP addres and the
netmask is equal to the network number, then the network contains the
address:

sub binary { return pack("C4", split(/\./, shift)); }

$ipaddr = "10.16.5.3";
if ((binary($ipaddr) & binary("255.255.0.0")) eq binary("10.16.0.0")) {
print "$ipaddr is in the network!";
}

I can understand why the OP prefers to use a module.

Hope this helps,

-- HansM
Mart van de Wege
2008-12-31 08:22:32 UTC
Permalink
Post by Hans Mulder
One way to check that a network contains an IP addres is to convert all
three numbers to binary. If the bitwise "and" of the IP addres and the
netmask is equal to the network number, then the network contains the
sub binary { return pack("C4", split(/\./, shift)); }
$ipaddr = "10.16.5.3";
if ((binary($ipaddr) & binary("255.255.0.0")) eq binary("10.16.0.0")) {
print "$ipaddr is in the network!";
}
I can understand why the OP prefers to use a module.
Why?

Silly question maybe, but I feel using binary ANDs is the most logical
way to handle this. After all, that's *exactly* what the netmask is
for.

Mart
--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.
Antgoodlife
2008-12-31 15:37:46 UTC
Permalink
Post by Mart van de Wege
Post by Hans Mulder
One way to check that a network contains an IP addres is to convert all
three numbers to binary.  If the bitwise "and" of the IP addres and the
netmask is equal to the network number, then the network contains the
sub binary { return pack("C4", split(/\./, shift)); }
$ipaddr = "10.16.5.3";
if ((binary($ipaddr) & binary("255.255.0.0")) eq binary("10.16.0.0")) {
   print "$ipaddr is in the network!";
}
I can understand why the OP prefers to use a module.
Why?
Silly question maybe, but I feel using binary ANDs is the most logical
way to handle this. After all, that's *exactly* what the netmask is
for.
Mart
--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.
Well, it seems I've actually been able to get the posted module to
work as well as the example above ... Here's the script incase anyone
has more comments. Thank you all for your assistance. (And it works
with .128 and/or other various masks...)

$ipaddr = "10.16.127.3";
$network = "10.16.0.0";
$netmask = "255.255.128.0";

if (isinnet($ipaddr,$network,$netmask)) {
print "$ipaddr is in $network/$netmask";
}
else {
print "$ipaddr not in network";
}

sub isinnet {
return(1) if ((binary($_[0]) & binary($_[2])) eq binary($_[1]));
}
sub binary { return pack("C4", split(/\./, shift)); }
Peter J. Holzer
2008-12-31 14:43:02 UTC
Permalink
Post by Hans Mulder
Post by Mirco Wahab
sub isInNet {
for( $_[2] =~ /255/g ) { # iterate over '255' mask fields
}
1
}
...
suffice? Of course, only for IPV4.
That worked in the early days when the only numbers allowed in a netmask
were 0 and 255. In 1993 the rules changed. Today netmasks can also
contain 128, 192, 224, 240, 248, 252 and 254.
The rules changed long before 1993. At the TU Vienna we've had a
(sub)netmask of 255.255.255.128 since at least 1988. You are probably
thinking about "classful routing". Until ca. 1993, the netmask was
implicit in the IP address - if the high byte was between 0 and 127, the
netmask was /8, if the high byte was between 128 and 191, it was /16 and
between 192 and 223 it was /24. Obviously this was only used for global
routing - a flat class A (with 16 million addresses) or class B (with
65536 addresses) network would have been impractical, so there was
always the possibility to split a "net" into "subnets", with arbitrary
subnet masks (our university split their class B network into 512
subnets). Later this was seen as wasteful, and classless routing was
introduced in the backbone, so that intermediate sized networks could be
assigned.

hp
John W. Krahn
2008-12-31 00:15:42 UTC
Permalink
Post by Antgoodlife
New to perl and this community...Hi all...
I've done some javascript / proxy pac work and I was curious if perl
has a built in (or if someone can point me to a module) that
determines if an IP is in a specific network? (Similar to proxy.pac
isinnet function)
#!/usr/bin/perl -w
# if ip 10.8.5.3 is in net 10.8.0.0 w/mask 255.255.0.0 return true
$ipaddr = "10.8.5.3"
print "$ipaddr is in the network!" if isinnet
($ipaddr,"10.8.0.0","255.255.0.0");
CIDR notation acceptance is a plus however not required for my
question.
$ perl -le'
use Socket;
sub isinnet {
my ( $ip_addr, $net, $mask ) = map inet_aton( $_ ), @_;
return $net eq ( $ip_addr & $mask );
}

my $ipaddr = "10.8.5.3";
print "$ipaddr is in the network!" if isinnet( $ipaddr, "10.8.0.0",
"255.255.0.0" );
'
10.8.5.3 is in the network!




John
--
Those people who think they know everything are a great
annoyance to those of us who do. -- Isaac Asimov
Ted Zlatanov
2008-12-31 16:22:20 UTC
Permalink
On Tue, 30 Dec 2008 11:40:19 -0800 (PST) Antgoodlife <***@gmail.com> wrote:

A> New to perl and this community...Hi all...
A> I've done some javascript / proxy pac work and I was curious if perl
A> has a built in (or if someone can point me to a module) that
A> determines if an IP is in a specific network? (Similar to proxy.pac
A> isinnet function)

A> For example :

A> #!/usr/bin/perl -w
A> # if ip 10.8.5.3 is in net 10.8.0.0 w/mask 255.255.0.0 return true
A> $ipaddr = "10.8.5.3"
A> print "$ipaddr is in the network!" if isinnet
A> ($ipaddr,"10.8.0.0","255.255.0.0");

A> CIDR notation acceptance is a plus however not required for my
A> question.

Net::Netmask should do what you need, and much more.

Ted

Loading...