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.
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
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.
> ("isinnet cpan")http://search.cpan.org/src/MIYAGAWA/HTTP-ProxyPAC-0.01/lib/HTTP/Proxy...
>
> --
> Klaus
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")) {
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.
$ 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
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
> 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.
>
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.
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
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]));
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