I'm parsing an LDAP record that has an IPv4 address as one attribute, and then a list of IPv4 subnets in <network>/<dotted quad netmask> format as another attribute. I need to be able to first verify that the single IP address is a member of one of the subnets in the list, and then get the netmask of that subnet. Net::Subnet will tell me if it's a member of one of the subnets, but I can't follow the flow well enough to modify it to give me the netmask of the subnet in question (I'm not sure if it's really clever or really poorly-written, but either way I've spent quite a bit of time staring at it and am now hopelessly stuck). I need to be able to run this on any given server, most of which I won't have access to and won't have Net::Subnet installed, so I'm trying to do this internally.
Here is the code I've got so far; it runs as-is and will tell me whether it finds a hit or not, but without being able to grab the netmask, it's not useful. I'm also open to other implementation suggestions, but at this point I'm really curious about how this is actually working (for example, WTF is "return !!0"???). All of the subs outside of main() are from Net::Subnet, but I pared them down to the minimum to get them to do what I needed.
(And to clarify, this is only a POC--the LDAP bits are represented here by $ip, @true, and @false. $ip is a member of @true, but not @false.)
#!/usr/bin/perl -w use strict; use Socket; sub subnet_matcher { @_ > 1 and goto &multi_matcher; my ($net, $mask) = split m[/], shift; return ipv4_matcher($net, $mask); } sub ipv4_matcher { my ($net, $mask) = @_; $net = inet_aton($net); $mask = inet_aton($mask); my $masked_net = $net & $mask; return sub { ((inet_aton(shift) // return !1) & $mask) eq $masked_ +net }; } sub multi_matcher { my @nets = map subnet_matcher($_), @_; return sub { $_->($_[0]) and return 1 for @nets; return !!0; } } sub main { my $ip = "65.181.207.232"; my @true = qw(10.96.2.0/255.255.254.0 10.123.50.0/255.255.255.0 72 +.24.196.0/255.255.255.0 72.24.137.192/255.255.255.192 10.122.50.0/255 +.255.255.0 65.181.207.128/255.255.255.128); my @false = qw(10.96.2.0/255.255.254.0 10.123.50.0/255.255.255.0 7 +2.24.196.0/255.255.255.0 72.24.137.192/255.255.255.192 10.122.50.0/25 +5.255.255.0); my $matcherTrue = subnet_matcher(@true); my $matcherFalse = subnet_matcher(@false); print "matcherTrue = " . ($matcherTrue->($ip) ? "yes\n" : "no\n"); print "matcherFalse = " . ($matcherFalse->($ip) ? "yes\n" : "no\n" +); } main;
In reply to finding netmask for "arbitrary" ip address by jasonl
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |